BimRevisionService::run | error: "BimRevisionService::runBimCompare | Forge error: INVALID_OTG_ERROR
RCA: BimRevisionService::run | Forge error: INVALID_OTG_ERROR
Error Log#
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_ERROR는 ForgeAgentErrorCode enum에 등록되지 않은 문자열이어서 ForgeErrorMapper가 UNKNOWN (REV1)으로 매핑하고, 비교 작업이 즉시 실패 처리되었습니다.
Technical Analysis#
Code Path#
- Entry point:
bim-revision-service.ts:149—BimRevisionService.run()SQS 메시지 수신 후 bim_revision_id=22420 처리 시작 - Forge 인증 및 상태 업데이트:
bim-revision-service.ts:166-168— Forge API 리전 설정, 인증, BIM comparison 상태를Comparing으로 업데이트 - BIM 비교 실행:
bim-revision-service.ts:169→bim-revision-service.ts:595—runBimCompare()호출
// 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-81—ForgeAgent.extract()가 두 URN의 OTG 데이터를 로드하여 비교 수행
// 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-663—bimCompareResults.Error에INVALID_OTG_ERROR문자열이 반환됨.ForgeErrorMapper.isIgnorableError()는 이 코드를 무시 가능한 에러로 인식하지 않음(ignorable은ROOM_EXT_ROOM_MAKER_IS_NOT_DEFINED만 해당).mapForgeErrorToRevisionError()에서ForgeAgentErrorCodeenum에INVALID_OTG_ERROR가 없어UNKNOWN (REV1)로 매핑
// 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로 업데이트
// 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 쿼리:
service:cupixworks-any-bimrevision-agent status:error @environment:production
service:cupixworks-any-bimrevision-agent @environment:production "22420"
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-... |
핵심 로그 원문:
{
"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"
}
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)#
-
INVALID_OTG_ERROR를ForgeAgentErrorCodeenum에 추가 —@cupix/forge-agents패키지(현재 v10.21.0)에 이 에러 코드가 등록되어 있지 않아 unmapped로 처리됨. 패키지 업데이트 또는 enum 추가 필요. -
ForgeErrorMapper에 OTG pending 에러 처리 로직 추가 —forge-error-mapper.ts:20-22에서INVALID_OTG_ERROR를 retry 가능한 에러로 분류하는 것을 검토. OTG 변환이 진행 중일 때는 일정 시간 대기 후 재시도하는 것이 적절함.
단기 개선 (1주 이내)#
-
BIM 비교 시작 전 OTG 변환 상태 확인 로직 추가 —
bim-revision-service.ts:169에서runBimCompare()호출 전에 Forge Manifest API를 통해 OTG 변환 완료 여부를 검증하는 pre-check 단계를 추가.pending상태이면 일정 시간 대기 후 재확인하거나, SQS 메시지를 visibility timeout으로 되돌려 나중에 재처리. -
재시도 메커니즘 구현 — OTG pending 상태는 일시적인 문제이므로, exponential backoff와 함께 최대 N회 재시도 후 최종 실패로 처리하는 로직을
runBimCompare내부 또는 SQS 메시지 레벨에서 구현.
장기 개선 (재발 방지)#
-
Forge 변환 완료 이벤트 기반 트리거 — 현재는 BIM revision 생성 시점에 바로 비교 에이전트를 호출하는 것으로 보임. Forge 변환 완료 webhook 또는 polling 기반으로 OTG 변환이 확실히 완료된 후에만 비교 작업을 큐에 넣는 아키텍처로 개선.
-
@cupix/forge-agents패키지의 에러 코드 체계 정비 — 새로운 Forge API 에러 코드가 추가될 때ForgeAgentErrorCodeenum에 반영되지 않는 문제가 반복될 수 있음. 패키지의 에러 코드 매핑을 정기적으로 Autodesk API 변경사항과 동기화하는 프로세스 필요.
Monitoring#
- BIM revision 에이전트의 OTG 관련 에러 빈도 모니터링:
service:cupixworks-any-bimrevision-agent "INVALID_OTG_ERROR" @environment:production
- Unmapped forge error code 발생 감지:
service:cupixworks-any-bimrevision-agent "Unmapped forge error code" @environment:production
- BIM revision 에이전트 전체 에러율 추적:
service:cupixworks-any-bimrevision-agent status:error @environment:production
Risk Assessment#
- Risk level: medium — OTG 변환 타이밍 문제로 특정 BIM 모델에서 반복 발생 가능. 현재 1건이지만 대규모 BIM 업로드 시 동시 발생 가능성 있음.
- 예상 복잡도: standard —
ForgeErrorMapper에 재시도 가능 에러 분류 추가 및 retry 로직 구현이 필요하나, 기존 에러 처리 구조가 잘 되어 있어 확장이 용이함.