ES /docs

BimRevisionService::run | error: "BimRevisionService::runBimCompare | Forge error: INVALID_OTG_ERROR

RCA: BimRevisionService::run | Forge error: INVALID_OTG_ERROR

Error Log#

Datadog Logs

text
BimRevisionService::run | error: "BimRevisionService::runBimCompare | Forge error: INVALID_OTG_ERROR - OTG status is pending: {}"

Impact#

  • Service: cupixworks-any-bimrevision-agent
  • Team: gad
  • 발생 횟수: 1
  • 최초 발생: 2026-04-06T11:29:43.578Z
  • 최근 발생: 2026-04-06T11:29:43.578Z

Root Cause Summary#

Autodesk Forge/APS 플랫폼에서 BIM 모델(bim_revision_id=22420)의 SVF2-to-OTG(Optimized Triangulation Graph) 변환이 아직 완료되지 않은 상태에서 BIM 비교(compare) 작업이 실행되었습니다. @cupix/forge-agents 라이브러리(v10.21.0)가 ForgeAgent.extract() 호출 시 OTG 데이터를 로드하려 했으나, Forge 측에서 OTG 상태가 pending이라는 응답을 반환했습니다. 이 에러 코드 INVALID_OTG_ERRORForgeAgentErrorCode enum에 등록되지 않은 문자열이어서 ForgeErrorMapperUNKNOWN (REV1)으로 매핑하고, 비교 작업이 즉시 실패 처리되었습니다.

Technical Analysis#

Code Path#

  • Entry point: bim-revision-service.ts:149BimRevisionService.run() SQS 메시지 수신 후 bim_revision_id=22420 처리 시작
  • Forge 인증 및 상태 업데이트: bim-revision-service.ts:166-168 — Forge API 리전 설정, 인증, BIM comparison 상태를 Comparing으로 업데이트
  • BIM 비교 실행: bim-revision-service.ts:169bim-revision-service.ts:595runBimCompare() 호출
typescript
// bim-revision-service.ts:595-639
private runBimCompare = async (cpBimRevision: CPBimRevision, cpPreviousBimRevision: CPBimRevision): Promise<void> => {
    logger.info('BimRevisionService::runBimCompare | begin');
    // ... URN/format/region 검증 ...
    const params: BimComparerParams = {
        apiConfig: { clientId: Environment.ADF_CLIENT_ID, clientSecret: Environment.ADF_CLIENT_SECRET },
        urn: cpBimRevision.forgeUrn,
        formatType: cpBimRevision.forgeFormatType,
        region: cpBimRevision.forgeRegion as 'US' | 'EMEA' | undefined,
        previousUrn: cpPreviousBimRevision.forgeUrn,
        // ...
    };
    const bimCompareResults = await this.bimCompareManager.execute(params);
  • Child process에서 Forge API 호출: bim-compare.process.ts:72-81ForgeAgent.extract()가 두 URN의 OTG 데이터를 로드하여 비교 수행
typescript
// bim-compare.process.ts:72-81
const result: ForgeAgent.Result = await ForgeAgent.extract(params.apiConfig, params.urn, {
    region: params.region,
    extractRoom: false,
    extractMeta: false,
    extractCompare: {
        urn: params.previousUrn,
        region: params.previousRegion,
        query: params.query
    }
});
  • 에러 코드 처리 (Failure point): bim-revision-service.ts:649-663bimCompareResults.ErrorINVALID_OTG_ERROR 문자열이 반환됨. ForgeErrorMapper.isIgnorableError()는 이 코드를 무시 가능한 에러로 인식하지 않음(ignorable은 ROOM_EXT_ROOM_MAKER_IS_NOT_DEFINED만 해당). mapForgeErrorToRevisionError()에서 ForgeAgentErrorCode enum에 INVALID_OTG_ERROR가 없어 UNKNOWN (REV1)로 매핑
typescript
// forge-error-mapper.ts:33-38
static mapForgeErrorToRevisionError(forgeErrorCode: ForgeAgentErrorCode | any): string {
    if (Object.values(ForgeAgentErrorCode).includes(forgeErrorCode)) {
        return ErrorCode.Revision.statusCode(forgeErrorCode);
    }
    logger.warn('ForgeErrorMapper::mapForgeErrorToRevisionError | Unmapped forge error code detected - forgeErrorCode: %s, type: %s, mapping to UNKNOWN (REV1)', forgeErrorCode, typeof forgeErrorCode);
    return ErrorCode.Revision.statusCode(ForgeAgentErrorCode.UNKNOWN);
}
  • 에러 전파: bim-revision-service.ts:660-662 — critical error로 분류되어 throw new Error(), run() 메서드의 catch 블록(bim-revision-service.ts:180-183)에서 BIM revision 상태를 Error로 업데이트
typescript
// bim-revision-service.ts:180-183
} catch (ec: any) {
    logger.error('BimRevisionService::run | error: %s', JSON.stringify(ec.message));
    await this.updateBimRevisionBimComparisonState(targetId, TESLA.UpdateBimRevisionRequest.BimComparisonStateEnum.Error, this.errorCode);
}

기대 동작: Forge 플랫폼이 OTG 변환을 완료한 상태에서 비교가 수행되어야 함. 정상적인 경우 ForgeAgent.extract()가 비교 결과(Origin, Compare report)를 반환.

실제 동작: Forge OTG 변환이 아직 pending 상태여서 INVALID_OTG_ERROR가 반환됨. 이 에러 코드는 ForgeAgentErrorCode enum에 없는 새로운 에러 코드로, unmapped critical error로 처리되어 즉시 실패.

Log Evidence#

사용한 Datadog 쿼리:

text
service:cupixworks-any-bimrevision-agent status:error @environment:production
text
service:cupixworks-any-bimrevision-agent @environment:production "22420"
text
service:cupixworks-worker @environment:production "bim" "revision"

에러 발생 타임라인 (bim_revision_id=22420):

시각 (UTC) 레벨 메시지
11:29:39.789 INFO AwsS3Manager::constructor | region: us-west-2
11:29:41.545 INFO BaseService::runByMessage | id: 22420
11:29:41.583 INFO CupixAuth::setSession | session_id: f6100a5c...
11:29:43.086 INFO BimRevisionService::runBimCompare | begin
11:29:43.087 INFO BimRevisionService::runBimCompare | params - urn: dXJu...j0xMA==, formatType: svf2, region: US
11:29:43.575 ERROR ForgeAgents - Error: { code: INVALID_OTG_ERROR, message: OTG status is pending: {} }
11:29:43.577 WARN CPBimRevision::validateBimComparerResult | forgeErrorCode: INVALID_OTG_ERROR
11:29:43.577 WARN ForgeErrorMapper::mapForgeErrorToRevisionError | Unmapped forge error code detected - forgeErrorCode: INVALID_OTG_ERROR, type: string, mapping to UNKNOWN (REV1)
11:29:43.577 ERROR BimRevisionService::runBimCompare | Critical Forge error detected - forgeErrorCode: INVALID_OTG_ERROR, mapped to revisionErrorCode: REV1
11:29:43.578 ERROR BimRevisionService::run | error: "BimRevisionService::runBimCompare | Forge error: INVALID_OTG_ERROR - OTG status is pending: {}"
11:29:44.307 INFO BaseService::cleanUpAnythingRelatedModel | path: /tmp/workspace/22420
11:29:44.335 INFO AwsQueueManager::deleteMessage | end - message id: 546867a6-...

핵심 로그 원문:

json
{
  "message": "ForgeAgents - Error: { code: INVALID_OTG_ERROR, message: OTG status is pending: {} }",
  "level": "error",
  "bim_revision_id": 22420,
  "previous_bim_revision_id": 22341,
  "user_id": 40133,
  "email": "aamnas@sixco-trojan.com",
  "team_id": 590,
  "domain": "gad",
  "host": "ip-10-1-100-190.us-west-2.compute.internal"
}
text
ForgeErrorMapper::mapForgeErrorToRevisionError | Unmapped forge error code detected - forgeErrorCode: INVALID_OTG_ERROR, type: string, mapping to UNKNOWN (REV1)

참고 — 정상 처리 비교: 같은 시간대에 bim_revision_id=22419 (다른 사용자/팀)는 약 36분 전에 정상 완료됨. 11,517개 modified, 1,091개 removed 요소를 처리한 성공 사례로, OTG 변환이 완료된 상태에서는 파이프라인이 정상 동작함을 확인.

upstream 서비스: cupixworks-worker에서 finalize_stuck_forge_translating_bims cron이 10분 간격으로 실행되고 있으나, bim_revision_id=22420에 대한 별도 에러 로그는 없음.

Fix Recommendation#

즉시 조치 (Critical)#

  1. INVALID_OTG_ERRORForgeAgentErrorCode enum에 추가@cupix/forge-agents 패키지(현재 v10.21.0)에 이 에러 코드가 등록되어 있지 않아 unmapped로 처리됨. 패키지 업데이트 또는 enum 추가 필요.

  2. ForgeErrorMapper에 OTG pending 에러 처리 로직 추가forge-error-mapper.ts:20-22에서 INVALID_OTG_ERROR를 retry 가능한 에러로 분류하는 것을 검토. OTG 변환이 진행 중일 때는 일정 시간 대기 후 재시도하는 것이 적절함.

단기 개선 (1주 이내)#

  1. BIM 비교 시작 전 OTG 변환 상태 확인 로직 추가bim-revision-service.ts:169에서 runBimCompare() 호출 전에 Forge Manifest API를 통해 OTG 변환 완료 여부를 검증하는 pre-check 단계를 추가. pending 상태이면 일정 시간 대기 후 재확인하거나, SQS 메시지를 visibility timeout으로 되돌려 나중에 재처리.

  2. 재시도 메커니즘 구현 — OTG pending 상태는 일시적인 문제이므로, exponential backoff와 함께 최대 N회 재시도 후 최종 실패로 처리하는 로직을 runBimCompare 내부 또는 SQS 메시지 레벨에서 구현.

장기 개선 (재발 방지)#

  1. Forge 변환 완료 이벤트 기반 트리거 — 현재는 BIM revision 생성 시점에 바로 비교 에이전트를 호출하는 것으로 보임. Forge 변환 완료 webhook 또는 polling 기반으로 OTG 변환이 확실히 완료된 후에만 비교 작업을 큐에 넣는 아키텍처로 개선.

  2. @cupix/forge-agents 패키지의 에러 코드 체계 정비 — 새로운 Forge API 에러 코드가 추가될 때 ForgeAgentErrorCode enum에 반영되지 않는 문제가 반복될 수 있음. 패키지의 에러 코드 매핑을 정기적으로 Autodesk API 변경사항과 동기화하는 프로세스 필요.

Monitoring#

  • BIM revision 에이전트의 OTG 관련 에러 빈도 모니터링:
text
service:cupixworks-any-bimrevision-agent "INVALID_OTG_ERROR" @environment:production
  • Unmapped forge error code 발생 감지:
text
service:cupixworks-any-bimrevision-agent "Unmapped forge error code" @environment:production
  • BIM revision 에이전트 전체 에러율 추적:
text
service:cupixworks-any-bimrevision-agent status:error @environment:production

Risk Assessment#

  • Risk level: medium — OTG 변환 타이밍 문제로 특정 BIM 모델에서 반복 발생 가능. 현재 1건이지만 대규모 BIM 업로드 시 동시 발생 가능성 있음.
  • 예상 복잡도: standard — ForgeErrorMapper에 재시도 가능 에러 분류 추가 및 retry 로직 구현이 필요하나, 기존 에러 처리 구조가 잘 되어 있어 확장이 용이함.