CPPointcloud::setLocalFilePath | undefined cpCluster
RCA: CPPointcloud::setLocalFilePath | undefined cpCluster
Error Log#
CPPointcloud::setLocalFilePath | undefined cpCluster
Impact#
- Service:
cupixworks-capture-3dreconstruction-instance - Team: walmart
- 발생 횟수: 1
- 최초 발생: 2026-04-08T07:48:55.513Z
- 최근 발생: 2026-04-08T07:48:55.513Z
Root Cause Summary#
densemapper(3D reconstruction 엔진)가 6개의 sub-cluster에 대한 pointcloud 파일을 생성했습니다. Tesla API에서 loadClusters로 가져온 cluster도 6개였으나(cluster count: 6), densemapper가 출력한 CPC 파일의 cluster ID 중 2개(1267289, 1267290)가 API에서 로드된 6개 cluster의 ID와 일치하지 않았습니다. 5번째 pointcloud 파일 walmart.675879_1267289.cpc를 처리할 때 getCPClusterFromId(1267289)가 undefined를 반환했고, setLocalFilePath에서 throw new Error('CPPointcloud::setLocalFilePath | undefined cpCluster')가 발생했습니다. 이는 densemapper 실행 중 Tesla API 측에서 cluster가 재구성(삭제/재생성)되어, 실행 전에 로드한 cluster ID 목록과 densemapper가 참조하는 cluster ID가 불일치한 데이터 동기화 문제입니다. job은 05:32:05Z에 시작하여 07:48:55Z에 실패했으며, 약 2시간 16분의 처리 시간 동안 cluster 상태가 변경되었을 가능성이 높습니다.
Technical Analysis#
Code Path#
- Entry point:
three-d-reconstruction-service.ts:57—ThreeDReconstruction.init() three-d-reconstruction-service.ts:99—run()호출, 순차적으로 리소스 로드 진행three-d-reconstruction-service.ts:112—loadClusters(cpCapture)— Tesla API에서 cluster 6개 로드 (info log:cluster count: 6). 이 중 4개의 ID(1267218, 1267220, 1267221, 1267264)는 densemapper 출력과 일치했으나, 나머지 2개는 1267289, 1267290과 일치하지 않음three-d-reconstruction-service.ts:118—runThreeDReconstruction(cpCapture)— densemapper 실행 (약 2시간 16분 소요), 결과로 6개 sub-cluster의 CPC 파일 생성 (ID: 1267218, 1267220, 1267221, 1267264, 1267289, 1267290)three-d-reconstruction-service.ts:120—checkPointcloudFiles(cpCapture)— 결과 디렉토리의 CPC 파일을 순회하며 cluster에 매핑 시도- Failure point:
cppointcloud.ts:114—_cpCluster가undefined이므로 throw
// cppointcloud.ts:100-115 — setLocalFilePath 내 cluster 매핑 로직
this._localFilePath = filePath;
this._name = path.basename(filePath);
const fileName = path.parse(filePath).name;
logger.debug('CPPointcloud::setLocalFilePath | fileName: %s', fileName);
const nameInfo = fileName.split('_');
let _cpCluster;
if (nameInfo.length == 2 && Number(nameInfo[1]) > 0) {
_cpCluster = this.cpCapture.getCPClusterFromId(Number(nameInfo[1]));
} else {
const normalCluster = this.cpCapture.cpClusters.find(cpCluster => cpCluster.srvCluster?.kind === 'normal');
_cpCluster = normalCluster || this.cpCapture.cpClusters[0];
}
if (_cpCluster == undefined) {
throw new Error('CPPointcloud::setLocalFilePath | undefined cpCluster');
}
파일명 walmart.675879_1267289에서 split('_')로 ["walmart.675879", "1267289"]을 추출하고, getCPClusterFromId(1267289)를 호출합니다. 그러나 loadClusters에서 로드된 cluster 목록에 1267289가 없으므로 undefined가 반환됩니다.
// cpcapture.ts:197-201 — getCPClusterFromId
getCPClusterFromId = (clusterId: number): CPCluster | undefined => {
if (clusterId == undefined || clusterId == Constants.UnknownId) return;
return this.cpClusters.find(x => x?.id === clusterId);
};
// three-d-reconstruction-service.ts:330-351 — checkPointcloudFiles
private checkPointcloudFiles = async (cpCapture: CPCapture): Promise<void> => {
logger.debug('ThreeDReconstruction::checkPointcloudFiles | begin');
const fileList = await CPUtils.getFiles(cpCapture.pointCloudDirPath);
const cpcFileList = fileList.filter(filePath => path.extname(filePath) === '.cpc' && !filePath.includes('mesh'));
if (cpcFileList.length < 1) {
logger.warn('ThreeDReconstruction::checkPointcloudFiles | not found cpc files');
throw new Error('not found cpc files');
}
for (let index = 0; index < cpcFileList.length; index++) {
const filePath = cpcFileList[index];
const cpPointcloud = new CPPointcloud();
cpCapture.addCPPointcloud(cpPointcloud);
if (!cpPointcloud.setLocalFilePath(filePath)) {
logger.warn('ThreeDReconstruction::checkPointcloudFiles | failed to set local file path - %s', filePath);
throw new Error('failed to set local file path');
}
}
};
기대 동작: densemapper가 생성한 모든 CPC 파일의 cluster ID가 loadClusters에서 로드한 cluster 목록의 ID와 일치해야 함.
실제 동작: API에서 6개 cluster를 로드했으나, densemapper 처리 중(약 2시간 16분) Tesla API 측에서 cluster가 재구성되어 일부 cluster ID가 변경됨. densemapper는 변경 후의 cluster ID(1267289, 1267290)를 파일명에 사용했으나, agent의 메모리에는 변경 전 cluster 목록만 캐싱되어 있어 불일치 발생.
Log Evidence#
Datadog 쿼리:
service:cupixworks-capture-3dreconstruction-instance status:error "CPPointcloud::setLocalFilePath"
에러 로그 (Datadog):
{
"timestamp": "2026-04-08T07:48:55.513Z",
"status": "error",
"message": "CPPointcloud::setLocalFilePath | undefined cpCluster",
"stack": "Error: CPPointcloud::setLocalFilePath | undefined cpCluster\n at CPPointcloud.setLocalFilePath (/tmp/agent/dist/app.cjs:7899:15)\n at ThreeDReconstruction.checkPointcloudFiles (/tmp/agent/dist/app.cjs:8330:27)\n at async ThreeDReconstruction.run (/tmp/agent/dist/app.cjs:8137:11)\n at async ThreeDReconstruction.init (/tmp/agent/dist/app.cjs:8087:7)",
"capture": { "id": 675879 },
"job": { "id": 1001788 },
"team": { "domain": "walmart", "id": 1124 },
"user": { "id": 44738, "email": "dcook@sletteninc.com" },
"region": "us-west-2"
}
Cupix Watch 쿼리 (Kibana):
Index: logstash-processing*
capture.id:675879 AND message:*checkPointcloudFiles*
결과 디렉토리의 CPC 파일 목록 (6개, Watch debug log):
[
"/tmp/workspace/walmart.675879_result/walmart.675879_1267218.cpc",
"/tmp/workspace/walmart.675879_result/walmart.675879_1267220.cpc",
"/tmp/workspace/walmart.675879_result/walmart.675879_1267221.cpc",
"/tmp/workspace/walmart.675879_result/walmart.675879_1267264.cpc",
"/tmp/workspace/walmart.675879_result/walmart.675879_1267289.cpc",
"/tmp/workspace/walmart.675879_result/walmart.675879_1267290.cpc"
]
성공적으로 매핑된 4개 cluster (Watch debug log):
CPPointcloud::setLocalFilePath | set cluster id: 1267218, name: Sub-Cluster 1
CPPointcloud::setLocalFilePath | set cluster id: 1267220, name: Sub-Cluster 2
CPPointcloud::setLocalFilePath | set cluster id: 1267221, name: Sub-Cluster 3
CPPointcloud::setLocalFilePath | set cluster id: 1267264, name: Sub-Cluster 4
5번째 파일에서 실패 (Watch debug → error log):
CPPointcloud::setLocalFilePath | set filePath: /tmp/workspace/walmart.675879_result/walmart.675879_1267289.cpc
CPPointcloud::setLocalFilePath | fileName: walmart.675879_1267289
CPPointcloud::setLocalFilePath | undefined cpCluster [ERROR]
타임라인 (Datadog info logs + Watch debug logs):
05:32:05Z—ThreeDReconstruction::init— job 1001788 시작05:32:05Z—ThreeDReconstruction::authenticate— session 인증 완료05:32:05Z—ThreeDReconstruction::run | begin05:32:05Z—JobManager::loadJob | end - job id: 100178805:32:06Z—loadVideos | video count: 105:32:06Z—loadClusters | cluster count: 6— API에서 6개 cluster 로드05:32:40Z—runThreeDReconstruction environments | domain: walmart— densemapper 실행 시작- (약 2시간 16분 처리)
07:48:55Z—checkPointcloudFiles | begin— 결과 디렉토리 스캔 시작07:48:55Z— 6개 CPC 파일 발견, 순차 처리 시작07:48:55Z— 1267218, 1267220, 1267221, 1267264 — 4개 성공적으로 cluster 매핑07:48:55Z— 1267289 파일 처리 시getCPClusterFromId(1267289)→undefined→ throw Error07:48:56Z—terminateService | force shutdown after 10 seconds— 서비스 종료
Fix Recommendation#
즉시 조치 (Critical)#
three-d-reconstruction-service.ts:120—checkPointcloudFiles호출 전에loadClusters(cpCapture)를 다시 호출하여, densemapper 실행 중 변경된 cluster 목록을 최신 상태로 갱신. 약 2시간의 처리 시간 동안 cluster가 재구성될 수 있으므로, 파일-cluster 매핑 직전에 cluster 목록을 refresh하는 것이 가장 안전한 수정
단기 개선 (1주 이내)#
cppointcloud.ts:113-115— 매핑 실패 시 throw 대신 warn 로깅 후 해당 pointcloud를 skip하는 방식으로 변경하여, 매핑 가능한 pointcloud는 정상적으로 업로드되도록 함- 현재 하나의 매핑 실패가 전체 job을 실패시키는 구조이므로, 부분 성공을 허용하는 로직 필요
- 매핑 실패한 cluster ID와 로드된 cluster ID 목록을 structured log로 출력하여 디버깅 용이성 향상
장기 개선 (재발 방지)#
- densemapper가 새 sub-cluster를 생성하는 경우에 대한 문서화 및 agent-densemapper 간 데이터 계약(contract) 명확화
- densemapper 실행 결과에 생성된 cluster ID 목록을 메타데이터로 포함시켜, agent가 사전에 필요한 cluster를 파악할 수 있도록 함
- cluster 생성과 pointcloud 파일 생성의 순서를 보장하는 프로세스 개선
Monitoring#
- 추가할 메트릭:
checkPointcloudFiles실패 시 capture ID, 매핑 실패 cluster ID를 structured log로 출력 - Datadog 알림:
service:cupixworks-capture-3dreconstruction-instance status:error "undefined cpCluster"
- densemapper 결과의 cluster 수와 API에서 로드된 cluster 수 불일치 모니터링
Risk Assessment#
- Risk level: medium
- 예상 복잡도: standard
- 장시간(2시간+) 처리되는 3D reconstruction job에서 처리 중 cluster가 재구성되는 시나리오에 해당. walmart 팀처럼 대규모 시설(다수의 sub-cluster)을 다루는 경우 재발 가능성이 있음. 현재는 1회 발생이나, 전체 job이 실패하여 약 2시간의 처리 시간이 소실되므로 사용자 영향이 큼.