ES /docs

CPPointcloud::setLocalFilePath | undefined cpCluster

RCA: CPPointcloud::setLocalFilePath | undefined cpCluster

Error Log#

Datadog Logs

text
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:57ThreeDReconstruction.init()
  • three-d-reconstruction-service.ts:99run() 호출, 순차적으로 리소스 로드 진행
  • three-d-reconstruction-service.ts:112loadClusters(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:118runThreeDReconstruction(cpCapture) — densemapper 실행 (약 2시간 16분 소요), 결과로 6개 sub-cluster의 CPC 파일 생성 (ID: 1267218, 1267220, 1267221, 1267264, 1267289, 1267290)
  • three-d-reconstruction-service.ts:120checkPointcloudFiles(cpCapture) — 결과 디렉토리의 CPC 파일을 순회하며 cluster에 매핑 시도
  • Failure point: cppointcloud.ts:114_cpClusterundefined이므로 throw
typescript
// 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가 반환됩니다.

typescript
// 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);
};
typescript
// 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 쿼리:

text
service:cupixworks-capture-3dreconstruction-instance status:error "CPPointcloud::setLocalFilePath"

에러 로그 (Datadog):

json
{
  "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):

text
Index: logstash-processing*
capture.id:675879 AND message:*checkPointcloudFiles*

결과 디렉토리의 CPC 파일 목록 (6개, Watch debug log):

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

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

text
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:05ZThreeDReconstruction::init — job 1001788 시작
  • 05:32:05ZThreeDReconstruction::authenticate — session 인증 완료
  • 05:32:05ZThreeDReconstruction::run | begin
  • 05:32:05ZJobManager::loadJob | end - job id: 1001788
  • 05:32:06ZloadVideos | video count: 1
  • 05:32:06ZloadClusters | cluster count: 6API에서 6개 cluster 로드
  • 05:32:40ZrunThreeDReconstruction environments | domain: walmart — densemapper 실행 시작
  • (약 2시간 16분 처리)
  • 07:48:55ZcheckPointcloudFiles | begin — 결과 디렉토리 스캔 시작
  • 07:48:55Z — 6개 CPC 파일 발견, 순차 처리 시작
  • 07:48:55Z — 1267218, 1267220, 1267221, 1267264 — 4개 성공적으로 cluster 매핑
  • 07:48:55Z — 1267289 파일 처리 시 getCPClusterFromId(1267289)undefinedthrow Error
  • 07:48:56ZterminateService | force shutdown after 10 seconds — 서비스 종료

Fix Recommendation#

즉시 조치 (Critical)#

  • three-d-reconstruction-service.ts:120checkPointcloudFiles 호출 전에 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 알림:
text
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시간의 처리 시간이 소실되므로 사용자 영향이 큼.