BimRevisionService::runBimCompare | Critical Forge error detected - forgeErrorCode: 908, mapped to r
RCA: BimRevisionService::runBimCompare — Critical Forge error 908 (REV908)
Overview#
What Happened#
cupixworks-any-bimrevision-agent이 BIM 모델 비교(runBimCompare)를 수행하는 도중 forge child process가 forgeErrorCode: 908을 반환하여 revision이 실패했다. 908은 "source/target 모델의 bounding box가 비교 한계(5000m)를 초과해 floating-point 정밀도 문제로 비교 신뢰성이 떨어진다"는 검증성 에러로, agent 측 결함이 아니라 입력 BIM 모델의 좌표/스케일 문제가 원인이다.
Quick Facts#
| Field | Value |
|---|---|
| exception.class | Error (generic Node.js Error thrown by runBimCompare) |
| exception.message | BimRevisionService::runBimCompare | Forge error: 908 - The source model bounding box is too large for reliable comparison (max extent: 5011.2m, limit: 5000m). ... |
| top_frame | packages/cupix-tesla-bim-revision-agent/src/bim-revision-service.ts:670 |
| revisionErrorCode | REV908 (via ForgeErrorMapper.mapForgeErrorToRevisionError) |
| env | production, regions us-west-2, eu-central-1 |
| tenant | cupix |
Affected Teams#
| Team / Domain | Error Count | Impact |
|---|---|---|
| exyte (BIM Revision pipeline) | 2 | 두 건의 revision 작업 실패 — 해당 facility는 BIM 비교/변경 추적 결과를 받지 못함 |
지난 7일 범위에서 동일 forgeErrorCode: 908 패턴이 다수 발생 (bim_id 1243, 19944, 19753, 19944, 16489 등). 본 cluster에 포함된 2건 외에도 동일 root cause로 추정되는 이벤트가 다수 있음.
Timeline#
- 2026-06-24 17:09 KST —
bim_id=16489,src_revision_id=24603비교 시작 → forge child process가Error code 908반환 (source extent 5011.2m, limit 5000m).BimRevisionService::runBimCompare가 throw →REVISE-ENDstatus=error. - 2026-06-24 18:08 KST — 동일 cluster의 두 번째 이벤트. 이번에는
forgeErrorCode: INVALID_OTG_ERROR(REV1로 매핑). 메시지 템플릿이 같아 fingerprint가 동일하게 grouping됨. - 2026-06-24 13:44 ~ 13:47 KST — 동일 서비스의 별도 incident(
2026-06-24-svc-cupixworks-any-bimrevision-agent--unknown-1)가 약 4시간 전에 자동 감지/해제됨. root_cause_types:unknown— 본 cluster와 직접 관련 여부 미확인.
Error Log#
BimRevisionService::runBimCompare | Critical Forge error detected - forgeErrorCode: 908, mapped to revisionErrorCode: REV908
Impact#
- Service:
cupixworks-any-bimrevision-agent - Team: exyte
- 발생 횟수: 2
- 최초 발생: 2026-06-24 17:09 KST
- 최근 발생: 2026-06-24 18:08 KST
영향 규모는 작지만(2건), 동일 root cause(forgeErrorCode: 908)는 지난 7일간 다수 facility에서 반복적으로 관찰됨. 영향 범위는 "비정상적으로 큰 좌표 스케일을 가진 BIM 모델을 업로드한 사용자"로 한정된다.
Root Cause Summary#
runBimCompare가 호출하는 forge child process(@cupix/forge-agents의 BIM Comparer)가, 입력된 source 또는 target SVF/OTG 모델의 bounding box max extent가 5000m 한계를 초과한 것을 감지하고 Error code 908을 반환한다. bim-revision-agent는 이 코드를 ForgeErrorMapper.mapForgeErrorToRevisionError로 REV908에 매핑한 뒤 logger.error(... Critical Forge error detected ...)를 출력하고 throw하므로, 에러 자체는 검증 로직이 정상적으로 동작한 결과이다. 즉 에이전트 결함이 아니라 입력 데이터(BIM 모델의 좌표계/스케일) 문제가 root cause이며, 단지 그 상황이 status:error 로그로 보고되기 때문에 error-sweeper가 클러스터로 묶었다.
Technical Analysis#
Code Path#
- Entry point:
packages/cupix-tesla-bim-revision-agent/src/bim-revision-service.ts:603—runBimCompare(cpBimRevision, cpPreviousBimRevision) - Forge 호출:
bim-revision-service.ts:647—this.bimCompareManager.execute(params)(child process를 통해@cupix/forge-agents의 BIM Comparer 실행) - 결과 분기:
bim-revision-service.ts:657-672—bimCompareResults.Error를 읽어 ignorable / critical 판정 - Failure point:
bim-revision-service.ts:667-670—mapForgeErrorToRevisionError(908)→REV908매핑 후logger.error와 함께 throw - Mapper:
packages/cupix-tesla-bim-revision-agent/src/util/forge-error-mapper.ts:33-39
const bimCompareResults = await this.bimCompareManager.execute(params);
const newBimOrigin = bimCompareResults?.Origin;
const report = bimCompareResults?.Compare;
if (report) {
logger.debug('BimRevisionService::runBimCompare | report.modified: %s', JSON.stringify(report.modified.map(m => ({ modelId: m.modelId, dbId: m.dbId }))));
logger.debug('BimRevisionService::runBimCompare | report.removed: %s', JSON.stringify(report.removed));
logger.debug('BimRevisionService::runBimCompare | report.exist: %s', JSON.stringify(report.exist.map(e => e != undefined ? { modelId: e.modelId, dbId: e.dbId } : null)));
}
const forgeErrorCode = bimCompareResults?.Error;
const forgeErrorMessage = bimCompareResults?.ErrorMessage;
if (forgeErrorCode) logger.warn('CPBimRevision::validateBimComparerResult | forgeErrorCode: %s', forgeErrorCode?.toString());
if (forgeErrorMessage) logger.warn('CPBimRevision::validateBimComparerResult | forgeErrorMessage: %s', forgeErrorMessage?.toString());
if (forgeErrorCode) {
if (ForgeErrorMapper.isIgnorableError(forgeErrorCode)) {
logger.warn('BimRevisionService::runBimCompare | Ignorable Forge error detected - forgeErrorCode: %s, message: %s', forgeErrorCode, forgeErrorMessage);
} else {
const errorCode = ForgeErrorMapper.mapForgeErrorToRevisionError(forgeErrorCode);
logger.error('BimRevisionService::runBimCompare | Critical Forge error detected - forgeErrorCode: %s, mapped to revisionErrorCode: %s', forgeErrorCode, errorCode);
this.setErrorCode(errorCode);
throw new Error(`BimRevisionService::runBimCompare | Forge error: ${forgeErrorCode} - ${forgeErrorMessage}`);
}
}
/** Forge error codes that do not require stopping the revision process */
private static ignorableErrorCodes: Set<ForgeAgentErrorCode> = new Set([
ForgeAgentErrorCode.ROOM_EXT_ROOM_MAKER_IS_NOT_DEFINED
]);
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);
}
기대 동작과 실제 동작이 일치한다: bounding box가 한계를 초과하는 입력에 대해 forge가 검증 에러를 돌려주면 agent는 그것을 REV908로 매핑·기록한 뒤 revision을 중단한다. 다만 현재 코드는 이 "사용자 입력 문제"를 logger.error로 기록하여 Datadog에서는 시스템 결함처럼 보이게 된다 (이것이 cluster를 만든 직접 원인).
ignorableErrorCodes set에는 현재 ROOM_EXT_ROOM_MAKER_IS_NOT_DEFINED만 포함돼 있어 COMPARE_EXT_* 계열 입력 검증 실패는 모두 critical path로 빠진다 (forge-error-mapper.ts:20-22).
Log Evidence#
Datadog query (cluster URL 기준, 14일 retention 범위 내):
service:cupixworks-any-bimrevision-agent status:error @environment:production "BimRevisionService::runBimCompare"
확장 쿼리 (지난 7일):
service:cupixworks-any-bimrevision-agent "bounding box is too large"
핵심 로그 (cluster 이벤트):
2026-06-24 17:09:06 error BimRevisionService::runBimCompare | Critical Forge error detected - forgeErrorCode: 908, mapped to revisionErrorCode: REV908
2026-06-24 17:09:06 error BimRevisionService::run | error: "BimRevisionService::runBimCompare | Forge error: 908 - The source model bounding box is too large for reliable comparison (max extent: 5011.2m, limit: 5000m). Large models cause floating-point precision issues that make comparison unreliable."
2026-06-24 17:09:06 warn CPBimRevision::validateBimComparerResult | forgeErrorMessage: The source model bounding box is too large for reliable comparison (max extent: 5011.2m, limit: 5000m). ...
2026-06-24 17:09:06 error ChildProcessManager::setupEventHandlers | Child process stderr: ForgeAgentError: The source model bounding box is too large for reliable comparison (max extent: 5011.2m, limit: 5000m). ...
2026-06-24 18:08:39 error BimRevisionService::runBimCompare | Critical Forge error detected - forgeErrorCode: INVALID_OTG_ERROR, mapped to revisionErrorCode: REV1
2026-06-24 18:08:39 error BimRevisionService::run | error: "BimRevisionService::runBimCompare | Forge error: INVALID_OTG_ERROR - OTG status is failed: [{\"type\":\"error\",\"message\":\"Extractor error code -777\",\"code\":\"TranslationWorker-InternalFailure\"}]"
REVISE-END info 로그(JSON)에서 영향 받은 entity ID를 확인할 수 있다:
{
"bim_id": 16489,
"src_revision_id": 24603,
"prev_revision_id": 21799,
"si_trace_id": "763b8c34-5ce4-456d-9117-208a2cbf160e",
"elapsed_ms": 6773,
"status": "error",
"error_message": "BimRevisionService::runBimCompare | Forge error: 908 - The source model bounding box is too large for reliable comparison (max extent: 5011.2m, limit: 5000m). ...",
"counts": {"total":0,"modified":0,"removed":0,"exist":0}
}
7일 패턴 (동일 root cause 다발):
2026-06-23 20:57:49 bim_id=1243 target extent 79903.2m
2026-06-23 04:08:31 bim_id=1243 target extent 79903.2m
2026-06-20 05:36:45 bim_id=19944 source extent 529197.5m
2026-06-19 23:15:49 bim_id=19753 target extent 1329398.3m
2026-06-24 17:09:06 bim_id=16489 source extent 5011.2m
extent 5011.2m처럼 한계에 매우 근접한 경우(0.2% 초과)부터 1,329,398m(약 1,329km, 좌표계 잘못 적용 의심)까지 폭넓게 나타난다.
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | Forge child process가 입력 모델의 bounding box max extent > 5000m를 감지하여 코드 908을 반환 → agent가 REV908로 매핑·throw | ChildProcessManager::setupEventHandlers | Child process stderr: ForgeAgentError: The source model bounding box is too large for reliable comparison (max extent: 5011.2m, limit: 5000m) 로그. bim-revision-service.ts:667-670에서 ForgeErrorMapper.mapForgeErrorToRevisionError(908) → REV908 throw. forge-error-mapper.ts:34 Object.values(ForgeAgentErrorCode).includes(908) 매핑. |
— | Confirmed |
| H2 | bim-revision-agent의 코드 결함 (null reference, race condition 등)으로 인한 시스템 에러 | — | 로그가 정확한 에러 메시지(bounding box too large)와 수치(max extent: 5011.2m, limit: 5000m)를 동반함. 코드 경로(bim-revision-service.ts:603-693)는 forge 결과를 그대로 매핑/throw할 뿐 검증 로직 자체에 결함 없음. isIgnorableError/mapForgeErrorToRevisionError는 단위 테스트가 존재(__tests__/util/forge-error-mapper.spec.ts). |
Rejected |
| H3 | Forge API 서비스 장애로 인한 false positive (실제 모델은 정상인데 잘못 908 반환) | — | 다양한 bim_id(1243, 16489, 19753, 19944)에서 일관되게 발생하며, 5011.2m / 79903.2m / 529197.5m / 1329398.3m 등 한계와 무관하게 모델별 고유 extent 수치가 보고됨. 단순 서비스 장애라면 동일 extent 수치가 반복되거나 다른 에러 코드가 섞여야 함. | Rejected |
| H4 | 상위 서비스 incident(2026-06-24-svc-cupixworks-any-bimrevision-agent--unknown-1, ~04:44 UTC 해제)와 연관된 잔여 영향 |
동일 서비스의 별도 cluster 다수가 같은 날 발생 → 자동 incident 생성 후 resolved. | 시간 간격이 4시간 이상이고, 본 cluster의 에러는 입력 데이터 검증 에러로 incident의 미지(unknown) root cause와 인과 관계가 보이지 않음. status-board 자체도 active: null. |
Rejected |
Fix Recommendation#
즉시 조치 (Critical)#
본 클러스터는 시스템 결함이 아닌 입력 데이터 문제다. 코드 수정 없이 운영 측면에서 처리하면 된다.
- exyte 팀에 해당 BIM 모델(
bim_id=16489의src_revision_id=24603)을 공유하여, 모델 좌표계/스케일 문제(extent 5011.2m, 한계 5000m에 매우 근접 — 0.2% 초과)를 사용자에게 안내하고 모델 origin 보정 또는 재업로드 요청. - 동일 root cause(
forgeErrorCode: 908)로 실패한 다른 facility 케이스(bim_id1243, 19753, 19944)도 함께 정리 — 동일한 사용자 행동 패턴인지 확인.
단기 개선 (1주 이내)#
- 로그 레벨 조정:
runBimCompare에서 forge가 돌려준 검증성 에러(COMPARE_EXT 계열, OTG 변환 실패 등) 중 "입력 데이터 문제로 명확히 판정된 코드"는logger.error대신logger.warn으로 낮춘다. 위치:packages/cupix-tesla-bim-revision-agent/src/bim-revision-service.ts:668. 이렇게 하면 error-sweeper 클러스터가 생성되지 않아 운영 노이즈를 줄일 수 있다 (참고:MEMORY.md의 "RCA Quality Patterns — 본 케이스는 입력 데이터 문제로 expected operational scenario에 해당"). - 에러 분류 명확화: 현재
ignorableErrorCodes는ROOM_EXT_ROOM_MAKER_IS_NOT_DEFINED1개뿐이다.COMPARE_EXT_*,INVALID_OTG_ERROR,INVALID_ARGUMENT_*같은 사용자 입력 검증 실패 코드를 별도 "user-input-error" 카테고리로 분리하고, agent log에서는 warn으로 기록하되 Tesla API에는 그대로 REV 코드로 전달하는 구조 검토. 위치:packages/cupix-tesla-bim-revision-agent/src/util/forge-error-mapper.ts:20-22.
장기 개선 (재발 방지)#
- 업로드 단계 사전 검증: Forge로 보내기 전, BIM 모델의 bounding box extent를 API/UI에서 미리 측정하여 5000m 한계 초과 시 사용자에게 즉시 명확한 에러 메시지를 제공. revision 파이프라인 끝에서 실패하기보다 업로드 시점에서 차단하는 편이 사용자 경험과 비용 모두 유리.
- revision 실패 코드 대시보드:
REVISE-ENDJSON 로그(status:"error"+error_message)를 기반으로 REV 코드별 실패 분포를 Datadog dashboard로 시각화하여, 시스템 에러(REV1/REV101 등)와 사용자 입력 에러(REV908, REV141 등)를 분리 모니터링.
Monitoring#
이미 충분한 로그가 남고 있다. 다음 쿼리를 dashboard timeseries widget에 등록하면 동일 패턴을 추적할 수 있다.
REV908 (bounding box 한계 초과) 발생률:
service:cupixworks-any-bimrevision-agent status:error "revisionErrorCode: REV908"
전체 BimRevision critical forge error 발생률 (REV* 매핑된 모든 케이스):
service:cupixworks-any-bimrevision-agent status:error "Critical Forge error detected"
bounding box too large 메시지 (모든 status):
service:cupixworks-any-bimrevision-agent "bounding box is too large"
REVISE-END status=error count (성공/실패 비율 측정용):
service:cupixworks-any-bimrevision-agent "BimRevisionService::REVISE-END" "\"status\":\"error\""
Risk Assessment#
- Risk level: low — 시스템 결함이 아닌 사용자 입력 데이터 문제. 영향 범위는 비정상적으로 큰 좌표 스케일의 BIM을 업로드한 사용자에 한정.
- 예상 복잡도: trivial — 코드 변경 불필요. 운영 안내 + 단기적으로 log level 낮춤(1줄 변경) 정도. 사전 검증 도입은 별도 ticket으로 분리 권장.