Forge Model Derivative SVF2 geometry 404 — missing resource
RCA: ChildProcessManager stderr — FAILED_TO_LOAD_GEOMETRIES
Overview#
What Happened#
2026-07-09 04:56:49 KST에 cupixworks-any-bimrevision-agent (region us-west-2, tenant cupix, team gilbaneco)의 BIM 비교 child process가 Autodesk Forge SVF2 geometry 파일(geometry_ptrs.hl)을 다운로드하지 못해 ForgeUtilsError: Failed to load geometries (errorCode: 'FAILED_TO_LOAD_GEOMETRIES')로 종료했다. 근본 원인은 Autodesk Forge 스토리지(autodesk-360-translation-storage-prod)에서 URN dNAYXwBuTf-N66i0f7dfww version 25 view 184bd667-bd21-470c-a4e5-99ba5fe1cea5의 리소스가 존재하지 않아 (errorCode: 'API_NOT_FOUND') SVF2GeometryWSSLoader가 3회 재시도 후 실패한 것이다. 상위 프로세스(BimCompareProcess)로 예외가 전파되면서 child process가 stderr로 스택을 뿜었고, ChildProcessManager의 stderr 리스너가 이를 error 레벨로 재기록했다.
Quick Facts#
| Field | Value |
|---|---|
| exception.class | ForgeUtilsError |
| exception.message | Failed to load geometries for 930f7b43-a283-a4f5-f18d-96282eb1de15 |
| errorCode | FAILED_TO_LOAD_GEOMETRIES (wraps API_NOT_FOUND) |
| top_frame | @cupixapps/forge-utils/convert-utils/svf2/svf2-reader.js:181:19 |
| upstream | Autodesk Forge (autodesk-360-translation-storage-prod) — HTTP 404 for geometry_ptrs.hl |
| forge-utils | 10.98.0 |
| forge-agents | 10.98.0 |
| env | production, us-west-2 |
Affected Teams#
| Team / Domain | Error Count | Impact |
|---|---|---|
gilbaneco (tenant cupix) |
1 revision job (fingerprint) | 해당 BIM revision 비교 작업 1건 실패. child process가 종료되어 결과 미생성. |
동일 서비스에서 유사한 ForgeUtilsError: Resource not found 패턴이 지난 14일 동안 17회 관찰됨 (여러 tenant/URN). 이번 클러스터의 fingerprint(503d6bf705bd685bbd3cbfac42fe7e77)는 errorCode: 'FAILED_TO_LOAD_GEOMETRIES' 문자열 자체이므로 최근 14일 내 첫 발생.
Timeline#
- 2026-07-09 04:56:16 KST — Child process 스폰됨 (AWS SDK v2 유지보수 경고가 stderr로 출력됨).
- 2026-07-09 04:56:49 KST —
SVF2GeometryWSSLoader가geometry_ptrs.hl다운로드 시도 1/3 실패 (Resource not found). - 2026-07-09 04:56:49 KST — 재시도 소진 후
ForgeUtilsError: Failed to load geometries(FAILED_TO_LOAD_GEOMETRIES) 발생, child process가 unhandled promise rejection으로 stderr에 스택 출력. - 2026-07-09 04:56:49 KST — 부모
ChildProcessManager의 stderr 리스너가 각 라인을logger.error로 기록 → Datadog에서 error 클러스터로 수집됨.
Error Log#
ChildProcessManager::setupEventHandlers | Child process stderr: errorCode: 'FAILED_TO_LOAD_GEOMETRIES'
Impact#
- Service:
cupixworks-any-bimrevision-agent - Team: gilbaneco
- 발생 횟수: 1
- 최초 발생: 2026-07-09 04:56:49 KST
- 최근 발생: 2026-07-09 04:56:49 KST
Root Cause Summary#
Autodesk Forge Model Derivative 스토리지(autodesk-360-translation-storage-prod)에서 SVF2 geometry 리소스(geometry_ptrs.hl)에 대한 GET 요청이 404를 반환했다. @cupixapps/forge-utils의 SVF2GeometryWSSLoader.downloadWithRetry는 3회 재시도 후에도 ForgeUtilsError: Resource not found (API_NOT_FOUND)를 그대로 throw했고, 상위 SVF2Reader.loadGeometries가 이를 FAILED_TO_LOAD_GEOMETRIES로 래핑한 뒤 CompareExtractor.compare → BimCompareProcess.execute 경로로 rethrow되었다. BimCompareProcess는 IPC 응답으로 error를 반환하는 대신 stderr로 그대로 스택을 노출했고, 부모의 ChildProcessManager.setupEventHandlers stderr 리스너가 이를 각각 logger.error 라인으로 재기록해 Datadog error 클러스터로 수집됐다. 즉, 근본 원인은 외부 종속성(Autodesk Forge)의 리소스 부재이고, 로컬 관측 방식(child process error가 IPC 실패 대신 stderr 대량 flood)에도 부차적 문제가 존재한다.
Technical Analysis#
Code Path#
- Entry point:
BimCompareManager.execute— parent 서비스가 child process에 IPC로execute메시지 전송. - Child dispatch:
BimCompareProcess.processMessage→BimCompareProcess.execute. - Forge 호출:
ForgeAgent.extract→CompareExtractor.compare→RevitEntityMap.loadGeometry→SVF2Reader.loadGeometries→SVF2GeometryWSSLoader.load/downloadWithRetry→ModelDataClient.getData/getBuffer→ForgeClient.handleApiError. - Failure point:
svf2-geometry-wss-loader.js:23—ForgeUtilsError: Resource not found(upstream 404). - Wrap point:
svf2-reader.js:181/170— geometry 로딩 실패를FAILED_TO_LOAD_GEOMETRIES로 재throw. - Error surface:
child-process.manager.tsstderr listener.
private async execute(params: BimComparerParams): Promise<ForgeAgent.Result> {
try {
this.log(`BimCompareProcess::execute | forge-agents version: ${forgeAgentsPkg.version}, spec_version: ${SpecVersion}`);
this.log('BimCompareProcess::execute | start');
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
}
});
...
} catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
const errorStack = error instanceof Error ? error.stack : undefined;
this.log(`BimCompareProcess::execute | error: ${errorMessage}`);
if (errorStack) {
this.log(`BimCompareProcess::execute | stack: ${errorStack}`);
}
throw error;
}
}
기대 동작: ForgeAgent.extract가 upstream 오류를 던지면 catch 블록이 로그하고 예외를 rethrow하며, BaseProcess가 부모에게 IPC 오류 응답을 보내야 한다. 실제 동작: rethrow된 예외가 BaseProcess.handleMessage 위쪽으로 전파되어 unhandled rejection이 되고, Node가 스택 트레이스를 stderr로 flush한다.
this.process.stderr?.on('data', (data: Buffer) => {
const text = data.toString();
logger.error(`ChildProcessManager::setupEventHandlers | Child process stderr: ${text}`);
});
기대 동작: child process가 정상적으로 stderr에 아무 것도 쓰지 않고 IPC로 오류를 반환. 실제 동작: unhandled promise rejection의 다중 라인 스택이 각 라인마다 별도의 error 로그로 기록되어 Datadog에서 다중 클러스터가 생성되고 (dbe3f79b, d5d87b89 등), 실제 원인을 클러스터 하나에서 파악하기 어렵다.
Log Evidence#
Datadog 쿼리:
service:cupixworks-any-bimrevision-agent "ChildProcessManager"
timeRange: 2026-07-08T19:50:00Z ~ 2026-07-08T20:10:00Z
Child process stderr에서 재구성한 스택 (동일 timestamp 2026-07-09 04:56:49 KST, 각 라인이 개별 로그 엔트리):
ForgeUtilsError: Failed to load geometries for 930f7b43-a283-a4f5-f18d-96282eb1de15
at async SVF2Reader.loadGeometries (@cupixapps/forge-utils/convert-utils/svf2/svf2-reader.js:170:36)
at async RevitEntityMap.loadGeometry (@cupixapps/forge-agents/extractor/compare-extractor/entity-map.js:174:32)
at async CompareExtractor.processTargetAndFillReport (@cupixapps/forge-agents/extractor/compare-extractor/compare-extractor.js:187:17)
at async CompareExtractor.compare (@cupixapps/forge-agents/extractor/compare-extractor/compare-extractor.js:112:13)
at async extractComparison (@cupixapps/forge-agents/app.js:133:20)
at async Object.extract (@cupixapps/forge-agents/app.js:82:25)
at async BimCompareProcess.execute (bim-compare.process.cjs:6459:22)
at async BimCompareProcess.processMessage (bim-compare.process.cjs:6435:16)
at async BimCompareProcess.handleMessage (bim-compare.process.cjs:5919:26) {
errorCode: 'FAILED_TO_LOAD_GEOMETRIES'
}
Cause chain (동일 timestamp에서 이어지는 내부 원인):
ForgeUtilsError: Resource not found: file/urn%3Aadsk.fluent%3Afs.file%3Aautodesk-360-translation-storage-prod%2FdNAYXwBuTf-N66i0f7dfww%2F25%2Foutput%2FResource%2F3D%20View%2F184bd667-bd21-470c-a4e5-99ba5fe1cea5-00dbea54%2Fgeometry_ptrs.hl?acmsession=...&disableIndexedDb=true
at ForgeClient.handleApiError (@cupixapps/forge-utils/server-utils/forge-client.js:90:31)
at ModelDataClient.getBuffer (@cupixapps/forge-utils/server-utils/forge-client.js:140:25)
at async ModelDataClient.getData (@cupixapps/forge-utils/server-utils/model-data.js:144:24)
at async SVF2GeometryWSSLoader.load (@cupixapps/forge-utils/convert-utils/svf2/svf2-geometry-wss-loader.js:61:45)
at async SVF2GeometryWSSLoader.downloadWithRetry (@cupixapps/forge-utils/convert-utils/svf2/svf2-geometry-wss-loader.js:23:24)
at async SVF2Reader.loadGeometries (@cupixapps/forge-utils/convert-utils/svf2/svf2-reader.js:181:19)
...
errorCode: 'API_NOT_FOUND'
Retry 흔적:
[SVF2GeometryWSSLoader] geometry_ptrs.hl failed (attempt 1/3): Resource not found: file/urn%3Aadsk.fluent%3Afs.file%3Aautodesk-360-translation-storage-prod%2FdNAYXwBuTf-N66i0f7dfww%2F25%2Foutput%2FResource%2F3D%20View%2F184bd667-bd21-470c-a4e5-99ba5fe1cea5-00dbea54%2Fgeometry_ptrs.hl?...
과거 14일 유사 발생 (service:cupixworks-any-bimrevision-agent "Resource not found" — 17건):
2026-07-08 17:21:13 — autodesk-translation-storage-emea-prod/Su3oePUsQ-Sj9ZyV5BAp1w/3/output/0/AECModelData.json (404)
2026-07-08 17:21:13 — autodesk-translation-storage-emea-prod/-Y5HFMK8QdK_pNoOOv0tkg/52/output/0/AECModelData.json (404)
2026-07-07 21:51:49 — autodesk-360-translation-storage-prod/w3cEko2vSNuSmggy9xLMHQ/23/output/0/AECModelData.json (404)
2026-07-07 21:51:47 — autodesk-360-translation-storage-prod/w3cEko2vSNuSmggy9xLMHQ/23/output/0/AECModelData.json (404)
2026-07-01 22:05:22 — autodesk-360-translation-storage-prod/w3cEko2vSNuSmggy9xLMHQ/22/output/0/AECModelData.json (404)
2026-07-01 02:46:27 — autodesk-360-translation-storage-prod/.../tesla-production/19448_1782841124608_HLC_SP_ALL_LEVELS.nwd (404)
2026-06-30 22:05:07 — autodesk-360-translation-storage-prod/.../19448_1782823829803_HLC_SP_ALL_LEVELS.nwd (404)
동일 root cause 유형(ForgeUtilsError: Resource not found)이 여러 URN/tenant에서 재발하고 있음 → 산발적이지만 지속되는 upstream 이슈이며, 한 revision job에 국한된 문제가 아님.
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | Autodesk Forge 스토리지에서 특정 URN version 25의 SVF2 geometry 리소스가 실제로 존재하지 않아 404가 반환됨 | stderr에 Resource not found: .../dNAYXwBuTf-N66i0f7dfww/25/.../geometry_ptrs.hl 및 errorCode: 'API_NOT_FOUND' 명시; retry 3회 모두 동일 실패; 지난 14일간 유사 404 17건 |
— | Confirmed |
| H2 | ChildProcess가 죽어서 child_process.error가 발생한 것 |
`ChildProcessManager::setupEventHandlers | Child process stderr:` 로그가 다수 | Child process closed, Child process exited, Child process error: 로그는 이 시각에 없음 — stderr 리스너만 트리거 |
| H3 | forge-agents/forge-utils 코드 결함 (SDK 자체 버그) | stack이 SDK 내부에서 발생 | SDK는 upstream HTTP 404를 정직하게 ForgeUtilsError로 래핑; 오류 자체는 정상 동작이며, retryable한 조건이 아님(리소스가 존재하지 않음) |
Rejected |
| H4 | 인증/세션(acmsession 토큰) 만료로 인한 404 |
URL에 acmsession=... 쿼리 존재 |
HTTP 상태 코드가 Resource not found(404)로 명시되어 인증 실패(401/403) 아님; 다른 tenant/URN도 동일 패턴 |
Rejected |
| H5 | Autodesk Forge translation job 미완료/삭제로 인해 특정 version output이 부재 | 여러 다른 URN version에서 동일 AECModelData.json/geometry_ptrs.hl 404 반복; 서로 다른 tenant(us-west-2 및 emea) |
직접 Forge API로 translation 상태 확인 필요 — uncertain -- needs verification | Inconclusive (H1의 사유로 유력) |
Fix Recommendation#
즉시 조치 (Critical)#
- 코드 변경 불필요 (upstream 종속성): 현재 이벤트는 Autodesk Forge의 리소스 부재로 인한 것으로, 로컬 코드 결함이 아니다. 대응은 운영 절차이다.
- 해당 revision job(URN
dNAYXwBuTf-N66i0f7dfwwversion 25, view184bd667-bd21-470c-a4e5-99ba5fe1cea5) 재검증: Autodesk Forge Model Derivative Manifest API로 translation 상태를 조회하고, 필요 시 re-translation을 요청하도록 tenantcupix/ teamgilbaneco운영자에게 hand-off. - 재발 tenant 목록 검토:
w3cEko2vSNuSmggy9xLMHQ,Su3oePUsQ-Sj9ZyV5BAp1w,-Y5HFMK8QdK_pNoOOv0tkg등도 최근 14일 내 다중 404 발생 → 배치 재변환 필요 여부 확인.
단기 개선 (1주 이내)#
- Child process 오류 표면화 개선 (
applications/agents/packages/base/src/manager/child-process.manager.ts:138): stderr 리스너가 각 라인을 별개 error 로그로 방출하는 대신, unhandled rejection을 IPC error response로 표준화해서 부모가 단일 로그로 기록하도록. 현재는 하나의 실패가 20+ error 라인 → 20+ 별개 fingerprint → 클러스터 중복. BimCompareProcess.execute재작성 (applications/agents/packages/cupix-tesla-bim-revision-agent/src/process/bim-compare.process.ts:105-115):throw error대신errorCode가API_NOT_FOUND/FAILED_TO_LOAD_GEOMETRIES등 입력 데이터 문제인 경우 부모에 warn/user-facing 오류로 표시하고, unhandled promise가 stderr로 새지 않도록BaseProcess.processMessage의 catch에서 항상 IPC 응답을 반환.- 로그 레벨 조정:
FAILED_TO_LOAD_GEOMETRIES처럼 upstream 데이터 문제로 확정된 오류는warn으로 낮추고,error는 실제 코드 결함/재시도 실패로 예약. (memory: cross-region/rate-limit 유형은 warn — MEMORY.md의 AUTH20022/20023 episode 참고.)
장기 개선 (재발 방지)#
- Autodesk Forge translation 상태 사전 확인: BIM revision 비교 시작 전에 Forge Model Derivative Manifest API로 대상 URN의 output이
success상태인지 pre-flight check. 실패 시 job을 실행하지 않고 pending 상태로 큐잉 후 재변환 요청. - 404 → 재변환 워크플로우:
Resource not found감지 시 자동으로 Forge translation을 재트리거하는 서브루틴 도입.data-pipeline-functions의 유사 패턴 참조 가능. - 관측 정리:
cupixworks-any-bimrevision-agent의 stderr flood 문제를 근본적으로 해결해 각 실패가 단일 클러스터로 잡히도록 (log key normalization). 이미 지난 14일 17건의Resource not found가 있으므로 fingerprint 통합 우선순위 높음.
Monitoring#
- Add a Datadog Log-based monitor tracking
FAILED_TO_LOAD_GEOMETRIESandResource not foundin this service. - Track upstream Autodesk Forge 404 rate as an SLI for BIM revision comparison.
Datadog queries (release dashboard timeseries widget용):
service:cupixworks-any-bimrevision-agent status:error "FAILED_TO_LOAD_GEOMETRIES"
service:cupixworks-any-bimrevision-agent status:error "Resource not found"
service:cupixworks-any-bimrevision-agent status:error "ChildProcessManager::setupEventHandlers"
Risk Assessment#
- Risk level: medium — 개별 revision job은 실패하지만 서비스 자체는 계속 동작. 그러나 upstream 문제가 지속적으로 재발 중이며, stderr flood로 관측이 오염됨.
- 예상 복잡도: standard — 즉시 조치는 운영 hand-off로 충분하고, 단기 개선은
child-process.manager.ts와bim-compare.process.ts에 국한된 error 핸들링 개선. 장기 개선(Forge pre-flight)은 별도 spec 필요.