ES /docs

MeshService::run | error: {"stack":"Error: Cannot read properties of undefined (reading 'filepaths')

RCA: MeshService::run | Cannot read properties of undefined (reading 'filepaths')

Overview#

What Happened#

2026-04-22T00:07:16Z에 cupixworks-any-mesh-agent 서비스에서 BIM ID 3309의 mesh 추출 작업이 실패했다. 자식 프로세스(MeshExtractorProcess)가 legacy SVF 경로로 실행되었으나, @cupix/app-mesh-extractor-v2mesh_extract() 함수가 undefined를 반환하여 extract.filepaths 접근 시 TypeError가 발생했다.

Quick Facts#

Field Value
exception.class TypeError
exception.message Cannot read properties of undefined (reading 'filepaths')
top_frame MeshExtractorProcess.execute (mesh-extractor.process.cjs:6361:28)
runtime Node.js (CommonJS bundle)
deploy Task Definition cupix-tesla-mesh-agent:7
env production, ap-southeast-2

Affected Teams#

Team / Domain Error Count Impact
multiplex-global 1 BIM ID 3309의 mesh 추출 실패, mesh_stateerror로 변경됨

Timeline#

  1. 2026-04-22T00:07:14Z — SQS 메시지 수신, BIM ID 3309 처리 시작 (BaseService::runByMessage)
  2. 2026-04-22T00:07:14Zmesh_stateextracting으로 업데이트
  3. 2026-04-22T00:07:14Z — 자식 프로세스 fork (PID 48, mesh-extractor.process.cjs)
  4. 2026-04-22T00:07:16Z — 자식 프로세스 ready, execute 시작
  5. 2026-04-22T00:07:16Z — legacy SVF 경로 진입, mesh_extract() 호출 → TypeError 발생
  6. 2026-04-22T00:07:16Zmesh_stateerror로 업데이트, 워크스페이스 정리, SQS 메시지 삭제

Error Log#

Datadog Logs

text
MeshService::run | error: {"stack":"Error: Cannot read properties of undefined (reading 'filepaths')
    at ChildProcessManager2.handleMessage (/tmp/agent/dist/app.cjs:1565:26)
    at ChildProcess.<anonymous> (/tmp/agent/dist/app.cjs:1503:16)
    at ChildProcess.emit (node:events:524:28)
    at ChildProcess.emit (node:domain:489:12)
    at emit (node:internal/child_process:950:14)
    at process.processTicksAndRejections (node:internal/process/task_queues:83:21)","message":"Cannot read properties of undefined (reading 'filepaths')"}

Impact#

  • Service: cupixworks-any-mesh-agent
  • Team: multiplex-global
  • 발생 횟수: 1
  • 최초 발생: 2026-04-22T00:07:16.397Z
  • 최근 발생: 2026-04-22T00:07:16.397Z

Root Cause Summary#

BIM ID 3309의 forge_format_typesvf2가 아닌 legacy SVF 포맷이어서, MeshExtractorProcess.execute()가 legacy 경로(MeshExtractor.mesh_extract())로 분기했다. 이 경로에서는 Forge OAuth token이 필요하지만, 부모 프로세스(MeshService.runMeshExtractor)가 token 파라미터를 전달하지 않아 undefined로 호출되었다. mesh_extract()undefined를 반환하면서, 후속 코드 extract.filepaths 접근 시 TypeError가 발생했다.

Technical Analysis#

Code Path#

  • Entry point: mesh-service.ts:101MeshService.run(targetId)
  • mesh-service.ts:112this.runMeshExtractor(cpBim) 호출
  • mesh-service.ts:184-194meshExtractManager.execute(params) 호출, token 파라미터 없음
  • mesh-extract.manager.ts:70childProcessManager.execute('execute', params) IPC 전송
  • mesh-extractor.process.ts:118 — 자식 프로세스 execute() 진입
  • mesh-extractor.process.ts:126params.formatType === 'svf2' 조건 검사 — false
  • Failure point: mesh-extractor.process.ts:153 — legacy 경로 MeshExtractor.mesh_extract(params.token!, ...) 호출
  • mesh-extractor.process.ts:156-157extract.filepaths 접근 시 TypeError

부모 프로세스(MeshService.runMeshExtractor)가 자식 프로세스에 전달하는 파라미터:

cupix-tesla-mesh-agent/src/mesh-service.ts:184-194typescript
const meshExtractorResults = await this.meshExtractManager.execute({
    apiConfig:{
        clientId: Environment.ADF_CLIENT_ID,
        clientSecret: Environment.ADF_CLIENT_SECRET
    },
    urn: cpBim.forgeUrn,
    path: cpBim.meshDirPath,
    timeOut: Environment.CPX_EXTRACTOR_TIMEOUT,
    formatType: cpBim.forgeFormatType,
    region: cpBim.forgeRegion
});

token 필드가 누락되어 있다. MeshExtractorParams 인터페이스에도 token이 정의되어 있지 않다:

cupix-tesla-mesh-agent/src/manager/mesh-extract.manager.ts:110-126typescript
export interface MeshExtractorParams {
    apiConfig: {
        readonly clientId: string;
        readonly clientSecret: string;
    };
    urn: string;
    path: string;
    timeOut: number;
    formatType: string;
    region: string;
}

자식 프로세스의 ExtractorParams 인터페이스에서는 token이 optional로 정의되어 있으나, legacy 경로에서는 이를 non-null assertion(!)으로 사용한다:

cupix-tesla-mesh-agent/src/process/mesh-extractor.process.ts:126-158typescript
if (params.formatType === 'svf2') {
    // svf2 경로: forge_bimmodel_extractor 사용 (token 불필요)
    // ... 성공적인 추출 후 filepaths 반환
} else {
    // legacy 경로: token이 필수지만 undefined로 전달됨
    extract = await MeshExtractor.mesh_extract(params.token!, params.urn, params.timeOut!, params.path);
}

const extractorResults = {
    filepaths: extract.filepaths  // extract가 undefined이면 TypeError
};

성공한 실행(BIM 2848)은 forge_format_typesvf2여서 svf2 경로를 탔고, process() 결과가 true로 정상 추출되었다.

Log Evidence#

Datadog에서 수집한 에러 로그:

text
Datadog query: service:cupixworks-any-mesh-agent status:error
Time: 2026-04-21T23:00:00Z to 2026-04-22T01:30:00Z
json
{
  "timestamp": "2026-04-22 09:07:16 KST",
  "status": "error",
  "message": "MeshService::run | error: {\"stack\":\"Error: Cannot read properties of undefined (reading 'filepaths')\\n    at ChildProcessManager2.handleMessage (/tmp/agent/dist/app.cjs:1565:26)\\n    at ChildProcess.<anonymous> (/tmp/agent/dist/app.cjs:1503:16)\"}"
}

Watch/Kibana에서 수집한 debug 로그가 핵심 증거이다. 실패한 BIM 3309의 자식 프로세스 실행 흐름:

text
Kibana query: ("MeshExtractorProcess::execute") AND level:debug
Index: logstash-agents*
Time: 2026-04-22T00:05:00Z → 2026-04-22T00:10:00Z
text
[09:07:16] [Child] MeshExtractorProcess::execute | start
[09:07:16] [Child] MeshExtractorProcess::execute | error: Cannot read properties of undefined (reading 'filepaths')
[09:07:16] [Child] MeshExtractorProcess::execute | stack: TypeError: Cannot read properties of undefined (reading 'filepaths')
    at MeshExtractorProcess.execute (/tmp/agent/dist/process/mesh-extractor.process.cjs:6361:28)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async MeshExtractorProcess.processMessage (/tmp/agent/dist/process/mesh-extractor.process.cjs:6303:16)
    at async MeshExtractorProcess.handleMessage (/tmp/agent/dist/process/mesh-extractor.process.cjs:5798:26)

execute | start 직후 에러가 발생했고, svf2 경로에서 출력되는 forge_bimmodel_extractor params 로그가 없다. 이는 params.formatType !== 'svf2'를 의미한다.

성공한 BIM 2848과 비교:

text
Kibana query: ("MeshExtractorProcess::execute") AND level:debug
Index: logstash-agents*
Time: 2026-04-21T23:14:00Z → 2026-04-21T23:22:00Z
text
[08:16:43] [Child] MeshExtractorProcess::execute - process() result: true (boolean)
[08:16:43] [Child] MeshExtractorProcess::execute - extracted 64 files: ["/tmp/workspace/2848/mesh/AECModelData.json", ...]
[08:16:43] [Child] MeshExtractorProcess::execute | Mesh extraction completed successfully

BIM 2848은 svf2 경로로 정상 추출되었다. process() result: true 로그는 svf2 전용이다.

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 BIM 3309의 forge_format_typesvf2가 아닌 legacy SVF이어서, token 없이 mesh_extract()를 호출했고 undefined가 반환됨 Watch debug 로그에서 forge_bimmodel_extractor params 로그 부재 (svf2 경로 미진입), `execute start직후filepathsTypeError 발생. 성공 사례(BIM 2848)는 svf2 경로로process() result: true로그 확인.MeshExtractorParams인터페이스에token 필드 미정의 (mesh-extract.manager.ts:110-126`)
H2 forge_bimmodel_extractor.process()가 false를 반환하여 추출 실패 svf2 경로에서 발생 가능한 실패 시나리오 Watch 로그에 process() result 로그가 없음 — svf2 경로에 진입하지 않았다. svf2 실패 시 throw new Error("forge_bimmodel_extractor failed") 메시지여야 함 (mesh-extractor.process.ts:150) Rejected
H3 자식 프로세스 타임아웃으로 인한 실패 ChildProcessOptions.executeTimeoutMs 설정 존재 에러 메시지가 Execution timeout이 아닌 TypeError: Cannot read properties of undefined. 실행 시작(09:07:16)과 에러(09:07:16)가 동일 초 — 타임아웃이 아님 Rejected
H4 MeshExtractor.mesh_extract()가 token undefined로 호출되어 인증 실패 후 undefined 반환 MeshService.runMeshExtractor에서 token 미전달 (mesh-service.ts:184-194), MeshExtractorParams에 token 필드 미정의, 자식 프로세스에서 params.token!으로 non-null assertion 사용 (mesh-extractor.process.ts:153) H1과 동일 원인의 세부 사항이므로 별도 가설이라기보다 H1의 구체적 메커니즘 Confirmed (H1의 세부)

Fix Recommendation#

즉시 조치 (Critical)#

  • mesh-extractor.process.ts:153 — legacy SVF 경로에서 params.tokenundefined인 경우 명시적 에러를 throw하도록 guard 추가. 이렇게 하면 extract.filepaths 접근 시 불명확한 TypeError 대신 원인이 명확한 에러 메시지가 출력된다.
  • mesh-extractor.process.ts:156-157extractundefined일 때의 null check 추가. extract?.filepaths로 안전하게 접근하거나, extractundefined이면 명시적 에러 throw.

단기 개선 (1주 이내)#

  • mesh-service.ts:174-197runMeshExtractor에서 legacy SVF 경로를 위한 Forge OAuth token을 획득하여 token 파라미터로 전달하는 로직 추가. ForgeAuth.authenticate() 호출 후 획득한 token을 params에 포함해야 한다.
  • mesh-extract.manager.ts:110-126MeshExtractorParams 인터페이스에 token?: string 필드 추가.
  • 또는 legacy SVF 포맷의 BIM 모델이 더 이상 지원되지 않는다면, formatType !== 'svf2'일 때 명시적으로 지원 중단 에러를 throw하고 불필요한 legacy 코드 경로를 제거하는 것이 더 깔끔한 접근이다.

장기 개선 (재발 방지)#

  • legacy SVF 포맷의 BIM 모델이 시스템에 얼마나 있는지 조사하여, 지원 여부를 결정. svf2 전환이 완료되었다면 legacy 경로를 제거.
  • forge_format_type별 처리 결과를 메트릭으로 수집하여, 어떤 포맷의 모델이 실패하는지 모니터링.

Monitoring#

  • mesh_extract 실패율을 forge_format_type별로 추적하는 메트릭 추가
  • Datadog 알림 쿼리:
text
service:cupixworks-any-mesh-agent status:error "Cannot read properties of undefined"
text
service:cupixworks-any-mesh-agent status:error "MeshService::run"

Risk Assessment#

  • Risk level: medium
  • 예상 복잡도: standard — legacy SVF 경로의 token 전달 로직 추가 또는 legacy 경로 제거 판단이 필요