ChildProcessManager::setupEventHandlers | Child process stderr: AssertionError [ForgeAgentError]: Mu
RCA: Derivative not found for modelId: 11 @ EntityMap.derivativesload()
Overview#
What Happened#
2026-05-27 09:17:56 UTC에 cupixworks-any-bimrevision-agent 서비스에서 BIM revision 비교 작업 중 ForgeAgentError (code 514)가 발생했다. @cupix/forge-agents 패키지의 EntityMap.load() 메서드가 Forge manifest에서 modelId 11에 해당하는 SVF derivative를 찾지 못해 assertion failure가 발생하고, 이것이 critical error로 분류되어 전체 revision 비교 작업이 중단되었다.
Quick Facts#
| Field | Value |
|---|---|
| exception.class | AssertionError [ForgeAgentError] |
| exception.message | Must not be a nullable value: Derivative not found for modelId: 11 @ EntityMap.derivativesload() |
| top_frame | entity-map.js:97 (compiled) |
| runtime | Node.js (child process via @cupix/forge-agents@10.98.0) |
| env | production, us-west-2 |
Affected Teams#
| Team / Domain | Error Count | Impact |
|---|---|---|
| exyte (BIM Revision) | 2 | bim_id 18046의 V2→V3 revision 비교 실패, 13,684개 element 업데이트 미반영 |
Timeline#
- 2026-05-27 09:16:32 UTC — BimRevisionService 시작 (bimRevisionId: 23760, bimId: 18046)
- 2026-05-27 09:16:50 UTC — REVISE-BEGIN, BIM 비교 시작
- 2026-05-27 09:17:56 UTC — EntityMap.load()에서 modelId 11 derivative 조회 실패, ForgeAgentError 514 발생
- 2026-05-27 09:17:56 UTC — Critical Forge error로 분류, revision 상태 Error로 전환
- 2026-05-27 09:17:57 UTC — 작업 공간 정리, REVISE-END (status: error)
Error Log#
ChildProcessManager::setupEventHandlers | Child process stderr: AssertionError [ForgeAgentError]: Must not be a nullable value: Derivative not found for modelId: 11 @ EntityMap.derivativesload()
Impact#
- Service:
cupixworks-any-bimrevision-agent - Team: exyte
- 발생 횟수: 2
- 최초 발생: 2026-05-27T09:17:56.519Z
- 최근 발생: 2026-05-27T09:17:56.521Z
Root Cause Summary#
Forge manifest에서 modelId 11에 해당하는 SVF derivative가 존재하지 않아 EntityMap.load() 내부의 CPAssert.assertDefined() assertion이 실패했다. 이 에러는 Autodesk Forge의 model derivative API에서 해당 모델의 변환(translation)이 아직 완료되지 않았거나, manifest에 해당 viewable이 등록되지 않은 상태에서 비교 작업이 시작된 것이 원인이다. @cupix/forge-agents 패키지는 derivative 조회 실패를 복구 불가능한 assertion error로 처리하며, ForgeErrorMapper에서 이를 ignorable error로 분류하지 않아 전체 작업이 중단된다.
Technical Analysis#
Code Path#
- Entry point:
bim-revision-service.ts:177—runBimCompare()호출 - Child process 실행:
bim-compare.manager.ts:65—childProcessManager.execute()via IPC - Forge extract 호출:
bim-compare.process.ts:72—ForgeAgent.extract()실행 - Failure point:
entity-map.js:86(compiled) —CPAssert.assertDefined(derivative, ...)assertion 실패
1. BimRevisionService에서 비교 시작:
await this.runBimCompare(this.cpBimRevision, this.cpPreviousBimRevision);
2. BimCompareManager가 child process로 작업 위임:
try {
const result = await this.childProcessManager.execute<ForgeAgent.Result>('execute', params);
logger.debug('BimCompareManager::execute | completed successfully');
return result;
} catch (error) {
logger.error('BimCompareManager::execute | error:', error);
const errorCode = ErrorCode.Agent.BimRevisionExtractorExecute;
if (this.setErrorCode) {
this.setErrorCode(errorCode);
}
throw error;
}
3. Child process에서 ForgeAgent.extract 실행:
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
}
});
4. EntityMap.load()에서 derivative 조회 실패 (compiled JS):
const derivative = modelId == null
? this.manifest_.default3dDerivative
: this.derivatives.find((d) => scope.getModelId(d) === modelId);
CPAssert.assertDefined(derivative, ForgeAgentErrorCode.DERIVATIVE_IS_NOT_DEFINED,
`Derivative not found for modelId: ${modelId} @ EntityMap.derivativesload()`);
modelId가 11로 전달되었으나 this.derivatives 배열에서 해당 modelId를 가진 derivative를 찾지 못해 undefined가 반환되고, assertDefined가 ForgeAgentError (code 514)를 throw한다.
5. Error propagation — ForgeErrorMapper가 critical error로 분류:
private static ignorableErrorCodes: Set<ForgeAgentErrorCode> = new Set([
ForgeAgentErrorCode.ROOM_EXT_ROOM_MAKER_IS_NOT_DEFINED
]);
DERIVATIVE_IS_NOT_DEFINED (514)는 ignorable set에 포함되지 않아 critical error로 처리된다.
if (forgeErrorCode) {
if (ForgeErrorMapper.isIgnorableError(forgeErrorCode)) {
logger.warn('BimRevisionService::runBimCompare | Ignorable Forge error detected...');
} else {
const errorCode = ForgeErrorMapper.mapForgeErrorToRevisionError(forgeErrorCode);
logger.error('BimRevisionService::runBimCompare | Critical Forge error detected...');
this.setErrorCode(errorCode);
throw new Error(`BimRevisionService::runBimCompare | Forge error: ${forgeErrorCode} - ${forgeErrorMessage}`);
}
}
Log Evidence#
사용한 Datadog 쿼리:
service:cupixworks-any-bimrevision-agent status:error @environment:production
service:cupixworks-any-bimrevision-agent "Derivative not found"
에러 발생 시 전체 로그 흐름:
2026-05-27 18:16:32 [info] BaseService::runByMessage | id: 23760
2026-05-27 18:16:32 [info] BimRevisionService::run | si_trace_id: a198b446-4fde-4f3e-8d38-5a934fdf3904
2026-05-27 18:16:32 [info] BimRevisionService::loadAllElements | begin - bimId: 18046, facilityKey: 5k6vfs
2026-05-27 18:16:50 [info] BimRevisionService::REVISE-BEGIN | {...}
2026-05-27 18:17:56 [error] ChildProcessManager::setupEventHandlers | Child process stderr: AssertionError [ForgeAgentError]: Must not be a nullable value: Derivative not found for modelId: 11 @ EntityMap.derivativesload()
2026-05-27 18:17:56 [error] BimRevisionService::runBimCompare | Critical Forge error detected - forgeErrorCode: 514, mapped to revisionErrorCode: REV514
2026-05-27 18:17:56 [error] BimRevisionService::run | error: "BimRevisionService::runBimCompare | Forge error: 514 - Must not be a nullable value: Derivative not found for modelId: 11 @ EntityMap.derivativesload()"
2026-05-27 18:17:56 [warn] CPBimRevision::validateBimComparerResult | forgeErrorMessage: Must not be a nullable value: Derivative not found for modelId: 11 @ EntityMap.derivativesload()
2026-05-27 18:17:57 [info] BimRevisionService::REVISE-END | {...status: "error", counts all zero...}
Full stack trace:
AssertionError [ForgeAgentError]: Must not be a nullable value: Derivative not found for modelId: 11 @ EntityMap.derivativesload()
at Object.assertDefined (/tmp/agent/dist/node_modules/.pnpm/@cupixapps+forge-agents@10.98.0_.../node_modules/@cupixapps/forge-agents/cpassert.js:27:19)
at RevitEntityMap.load (/tmp/agent/dist/node_modules/.pnpm/@cupixapps+forge-agents@10.98.0_.../node_modules/@cupixapps/forge-agents/extractor/compare-extractor/entity-map.js:97:33)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async CompareExtractor.collectPrevEntities (/tmp/agent/dist/.../compare-extractor.js:991:13)
at async CompareExtractor.compare (/tmp/agent/dist/.../compare-extractor.js:91:38)
at async extractComparison (/tmp/agent/dist/.../app.js:133:20)
at async Object.extract (/tmp/agent/dist/.../app.js:82:25)
at async BimCompareProcess.processMessage (/tmp/agent/dist/process/bim-compare.process.cjs:6435:16)
에러가 CompareExtractor.collectPrevEntities에서 발생한 것으로 보아, 이전 revision(V2)의 manifest에서 modelId 11을 찾으려 한 것이다. 현재 revision(V3)의 src_forge_urn에 version=11이 인코딩되어 있으므로, 새 revision에는 11개의 viewable model이 있지만, 이전 revision(V2)의 manifest에는 modelId 11이 존재하지 않는 상태다.
Key identifiers:
- bim_id: 18046
- facilityKey: 5k6vfs
- src_revision_id: 23760 (V3), prev_revision_id: 21803 (V2)
- src_forge_urn: version=11, prev_forge_urn: version=2
- cp_elements_count: 13,684 (created: 12,337, deleted: 1,347)
- Elapsed time: ~85 seconds
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | V3에 새 model이 추가되어 V2 manifest에 존재하지 않는 modelId 11을 조회하려 함 | src_forge_urn version=11, prev_forge_urn version=2; collectPrevEntities에서 실패; 12,337개 created elements는 새 model 추가를 시사 |
— | Confirmed |
| H2 | Forge derivative 변환(translation)이 완료되지 않은 상태에서 비교 시작 | derivative 관련 assertion failure | 만약 translation 미완료라면 manifest 자체를 로드 못하는 다른 에러가 발생할 것; stack trace가 manifest는 정상 로드 후 find에서 실패 | Rejected |
| H3 | Forge API 일시적 장애로 manifest 데이터 불완전 반환 | — | 동일 시간대 다른 revision 작업들은 정상 수행됨 (23752, 23758, 23759); 단일 bim_id에서만 발생 | Rejected |
Fix Recommendation#
즉시 조치 (Critical)#
@cupix/forge-agents패키지의entity-map.js:83-86에서 derivative를 찾지 못할 때 assertion 대신 graceful handling이 필요하다.- 다만 이것은 npm 패키지 내부이므로, 에이전트 서비스 측에서 이 에러를 처리하는 것이 더 현실적이다.
forge-error-mapper.ts:20-22에서DERIVATIVE_IS_NOT_DEFINED(514)를 ignorable set에 추가하거나, 또는 partial failure로 처리하여 해당 modelId만 건너뛰고 나머지 비교를 계속하도록 변경한다.- 파일:
packages/cupix-tesla-bim-revision-agent/src/util/forge-error-mapper.ts:20
단기 개선 (1주 이내)#
CompareExtractor.collectPrevEntities호출 전에 이전 revision의 manifest에 포함된 modelId 목록을 확인하고, 새 revision에만 존재하는 modelId는 비교 대상에서 제외하는 전처리 로직 추가.bim-revision-service.ts의runBimCompareparams 생성 시,query.entities에서 이전 revision에 없는 modelId를 가진 entity를 필터링하는 방안 검토.
장기 개선 (재발 방지)#
@cupix/forge-agents패키지에서 derivative 미발견 시 assertion 대신modelIdsFailedToLoad배열에 추가하고 나머지 model은 정상 처리하도록 partial-failure 패턴 적용 (패키지 업스트림 변경 필요).- Revision 비교 시 model 구조 변경(model 추가/삭제) 시나리오에 대한 통합 테스트 추가.
Monitoring#
DERIVATIVE_IS_NOT_DEFINED에러 빈도 추적:
service:cupixworks-any-bimrevision-agent "Derivative not found for modelId" status:error
- Forge error code 514 발생률 대시보드:
service:cupixworks-any-bimrevision-agent "Critical Forge error detected" "514"
Risk Assessment#
- Risk level: medium
- 예상 복잡도: standard —
ForgeErrorMapper에 ignorable 추가는 간단하지만, partial failure 처리를 올바르게 구현하려면 비교 결과 무결성 검증이 필요하다. 해당 에러는 model 구조 변경(viewable 추가) 시 재발할 수 있다.