ES /docs

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로 스택을 뿜었고, ChildProcessManagerstderr 리스너가 이를 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#

  1. 2026-07-09 04:56:16 KST — Child process 스폰됨 (AWS SDK v2 유지보수 경고가 stderr로 출력됨).
  2. 2026-07-09 04:56:49 KSTSVF2GeometryWSSLoadergeometry_ptrs.hl 다운로드 시도 1/3 실패 (Resource not found).
  3. 2026-07-09 04:56:49 KST — 재시도 소진 후 ForgeUtilsError: Failed to load geometries (FAILED_TO_LOAD_GEOMETRIES) 발생, child process가 unhandled promise rejection으로 stderr에 스택 출력.
  4. 2026-07-09 04:56:49 KST — 부모 ChildProcessManager의 stderr 리스너가 각 라인을 logger.error로 기록 → Datadog에서 error 클러스터로 수집됨.

Error Log#

Datadog Logs

text
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-utilsSVF2GeometryWSSLoader.downloadWithRetry는 3회 재시도 후에도 ForgeUtilsError: Resource not found (API_NOT_FOUND)를 그대로 throw했고, 상위 SVF2Reader.loadGeometries가 이를 FAILED_TO_LOAD_GEOMETRIES로 래핑한 뒤 CompareExtractor.compareBimCompareProcess.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.processMessageBimCompareProcess.execute.
  • Forge 호출: ForgeAgent.extractCompareExtractor.compareRevitEntityMap.loadGeometrySVF2Reader.loadGeometriesSVF2GeometryWSSLoader.load/downloadWithRetryModelDataClient.getData/getBufferForgeClient.handleApiError.
  • Failure point: svf2-geometry-wss-loader.js:23ForgeUtilsError: Resource not found (upstream 404).
  • Wrap point: svf2-reader.js:181 / 170 — geometry 로딩 실패를 FAILED_TO_LOAD_GEOMETRIES로 재throw.
  • Error surface: child-process.manager.ts stderr listener.
applications/agents/packages/cupix-tesla-bim-revision-agent/src/process/bim-compare.process.ts:67-115typescript
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한다.

applications/agents/packages/base/src/manager/child-process.manager.ts:138-141typescript
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 쿼리:

text
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, 각 라인이 개별 로그 엔트리):

text
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에서 이어지는 내부 원인):

text
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 흔적:

text
[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건):

text
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.hlerrorCode: '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-N66i0f7dfww version 25, view 184bd667-bd21-470c-a4e5-99ba5fe1cea5) 재검증: Autodesk Forge Model Derivative Manifest API로 translation 상태를 조회하고, 필요 시 re-translation을 요청하도록 tenant cupix / team gilbaneco 운영자에게 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 대신 errorCodeAPI_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_GEOMETRIES and Resource not found in this service.
  • Track upstream Autodesk Forge 404 rate as an SLI for BIM revision comparison.

Datadog queries (release dashboard timeseries widget용):

text
service:cupixworks-any-bimrevision-agent status:error "FAILED_TO_LOAD_GEOMETRIES"
text
service:cupixworks-any-bimrevision-agent status:error "Resource not found"
text
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.tsbim-compare.process.ts에 국한된 error 핸들링 개선. 장기 개선(Forge pre-flight)은 별도 spec 필요.