ES /docs

not found refined align_preview_meta_refinement_with_prior_map.json

RCA: not found refined align_preview_meta_refinement_with_prior_map.json

Overview#

What Happened#

2026-07-14 15:37 KST 경 cupixworks-capture-refinement-arm-instance (Capture Refinement Agent) 가 서로 다른 두 개의 캡처(734539, 734484) 처리 중 copyAlignmentToEfs 단계에서 refinement 결과 파일 align_preview_meta_refinement_with_prior_map.json 을 로컬 결과 디렉토리에서 찾지 못해 job 을 실패시켰다. Refinement 는 완료되었지만 scenemapper child process 가 이 특정 산출물을 생성하지 못한 상태로 종료된 것으로, 두 캡처 모두 clark-vdc 팀(us-west-2) 소속이다.

Quick Facts#

Field Value
exception.class Error
exception.message not found refined align_preview_meta_refinement_with_prior_map.json
top_frame RefinementService.copyAlignmentToEfs (/tmp/agent/dist/app.cjs:7467:15) (source: applications/agents/packages/cupix-capture-refinement-agent/src/refinement-service.ts:381)
runtime Node.js agent bundle (/tmp/agent/dist/app.cjs) on arm instance
env production, us-west-2
affected captures 734539 (job 1194919, host 4e2b6d37118e), 734484 (job 1194920, host 4769d35ddbc5)

Affected Teams#

Team / Domain Error Count Impact
clark-vdc (team.id 87) 2 Capture refinement job 이 실패 처리되어 해당 두 캡처의 refined alignment / preview 산출물이 EFS 로 승격되지 못함

Timeline#

  1. 2026-07-14 15:30 KST — 다수의 refinement 서비스 인스턴스(다른 hosts)가 동시에 job 을 loadJob 하며 정상 부트업 (RefinementService::run | begin, JobManager::loadJob | end 로그 확인)
  2. 2026-07-14 15:36:59 KST — scenemapper 로부터 Grid map is not available or empty. Cannot calculate alignment quality. warning 발생 ([124603.75] 스코어 태그)
  3. 2026-07-14 15:37:45 KST — capture 734539 (job 1194919, host 4e2b6d37118e) 에서 Error: not found refined align_preview_meta_refinement_with_prior_map.json 발생 (first_seen)
  4. 2026-07-14 15:38:17 KST — capture 734484 (job 1194920, host 4769d35ddbc5) 에서 동일 에러 발생 (last_seen). 이후 각 인스턴스는 RefinementService::terminateService | force shutdown after 10 seconds 로 강제 종료

Error Log#

Datadog Logs

text
not found refined align_preview_meta_refinement_with_prior_map.json

Stack (from Datadog raw log attribute stack):

Error stack (Datadog attributes.stack)text
Error: not found refined align_preview_meta_refinement_with_prior_map.json
    at RefinementService.copyAlignmentToEfs (/tmp/agent/dist/app.cjs:7467:15)
    at async RefinementService.run (/tmp/agent/dist/app.cjs:7210:11)
    at async RefinementService.init (/tmp/agent/dist/app.cjs:7165:7)

Impact#

  • Service: cupixworks-capture-refinement-arm-instance
  • Team: clark-vdc
  • 발생 횟수: 2 (클러스터 집계 기준)
  • 최초 발생: 2026-07-14 15:37 KST
  • 최근 발생: 2026-07-14 15:38 KST
  • 부가 영향: 실패한 job 은 updateErrorActionJob('refinement') 로 마킹 (refinement-service.ts:109). 후속 3D reconstruction 파이프라인은 refined alignment 파일 없이는 dense mapping 판단(checkAndCopyForReconstruction) 을 진행하지 못하므로 해당 캡처 두 건은 재처리(재-refinement) 없이는 완료되지 않는다.

Root Cause Summary#

Refinement agent 는 scenemapper child process 를 실행한 뒤 copyAlignmentToEfs 단계에서 로컬 결과 디렉토리(cpCapture.resultsDirPath) 에 있는 refinement 산출물들을 EFS 로 복사한다. 이 함수는 align_preview_meta_refinement_with_prior_map.json 이 존재하지 않으면(CPUtils.getFileSize(...) <= 0) ErrorCode.ScenemapperUtils.RefinerNotFoundInputFiles 를 세팅하고 예외를 던지도록 하드 게이팅되어 있다. 두 캡처 모두 scenemapper 자체는 실행됐지만("Grid map is not available or empty" warning 이 scenemapper 로부터 선행 출력됨) alignment 품질을 계산할 수 있는 유효한 grid map 이 없어 해당 산출물을 생성하지 못한 채 refinement 를 종료했다. 즉, 근본 원인은 이 두 캡처의 입력(alignment_archive.bin 또는 unrefined cluster) 이 scenemapper 가 유의미한 refinement 결과를 만들기에 부족한 상태였고, agent 는 이러한 "scenemapper 는 성공했으나 특정 산출물이 비었음" 상태를 별도 error code 없이 단일 RefinerNotFoundInputFiles 로 처리하고 있어 상위 파이프라인이 원인을 구분하지 못하고 있다는 점이다.

Technical Analysis#

Code Path#

  • Entry point: applications/agents/packages/cupix-capture-refinement-agent/src/refinement-service.ts:79RefinementService.run()
  • 전체 흐름: run → runRefinement (scenemapper child process 실행) → copyAlignmentToEfs (결과 파일 EFS 복사)
  • Failure point: applications/agents/packages/cupix-capture-refinement-agent/src/refinement-service.ts:381

run() 의 orchestration:

applications/agents/packages/cupix-capture-refinement-agent/src/refinement-service.ts:79-111typescript
private run = async (): Promise<void> => {
	logger.info('RefinementService::run | begin');
	try {
		const srvJob = await this.jobManager.loadJob(Environment.CPX_JOB_ID as number);
		await this.jobManager.updateRunningActionJob('refinement');
		const cpCapture = srvJob ? await this.createCPCaptureByJob(srvJob) : undefined;
		if (cpCapture) {
			this.checkInputFiles();
			// ...
			await this.runRefinement(cpCapture);
			await this.copyAlignmentToEfs(cpCapture);   // ← 여기서 throw
			await this.copyPreviewImageToEfs(cpCapture);
			await this.checkAndCopyForReconstruction(cpCapture);
			// ...
		}
		logger.info('RefinementService::run | end');
		await this.jobManager.updateCompleteActionJob('refinement', TESLA.UpdateJobRequest.StateEnum.Stopped);
	} catch (error) {
		logger.error('RefinementService::run | end - %s', JSON.stringify(error));
		await this.jobManager.updateErrorActionJob('refinement');
	}
};

문제의 게이트:

applications/agents/packages/cupix-capture-refinement-agent/src/refinement-service.ts:370-382typescript
const alignPreviewRefinementFileEfsPath = path.join(skatMasterEfsPath, Constants.DefaultAlignPreviewRefinementJsonFileName);
const alignPreviewRefinementFileLocalPath = path.join(cpCapture.resultsDirPath, Constants.DefaultAlignPreviewRefinementJsonFileName);
if (CPUtils.getFileSize(alignPreviewRefinementFileLocalPath) > 0) {
	const start = new Date().getTime();
	this.renameExistingFile(alignPreviewRefinementFileEfsPath);
	fs.copyFileSync(alignPreviewRefinementFileLocalPath, alignPreviewRefinementFileEfsPath);
	const durationTime = new Date().getTime() - start;
	logger.debug('RefinementService::copyAlignmentToEfs | copy refined %s - duration: %d ms, size: %d bytes', Constants.DefaultAlignPreviewRefinementJsonFileName, durationTime, CPUtils.getFileSize(alignPreviewRefinementFileLocalPath));
} else {
	logger.warn('RefinementService::copyAlignmentToEfs | not found refined %s', Constants.DefaultAlignPreviewRefinementJsonFileName);
	this.jobManager.setErrorCode(ErrorCode.ScenemapperUtils.RefinerNotFoundInputFiles);
	throw new Error('not found refined align_preview_meta_refinement_with_prior_map.json');
}

DefaultAlignPreviewRefinementJsonFileName 상수 정의:

applications/agents/packages/cupix-capture-refinement-agent/src/config/constants.ts:22typescript
export const DefaultAlignPreviewRefinementJsonFileName = 'align_preview_meta_refinement_with_prior_map.json';

scenemapper wrapper 는 execute 에서 예외를 잡아 warn 으로만 로깅하고, 실제 산출물 존재 여부는 후행 파일 시스템 체크에 위임한다:

applications/agents/packages/cupix-capture-refinement-agent/src/manager/scenemapper.manager.ts:49-58typescript
execute = async (params: RefinerParams): Promise<void> => {
	await this.ensureInitialized();
	try {
		await this.childProcessManager.execute('execute', params);
	} catch (error) {
		logger.warn('ScenemapperManager::execute | error - %s', error);
		if (this.setJobErrorCode) this.setJobErrorCode(ErrorCode.ScenemapperUtils.RefinerExecute);
		throw error;
	}
};

기대 동작 vs 실제 동작:

  • 기대: scenemapper 가 유효한 grid map 을 이용해 refinement 를 수행하고 align_preview_meta_refinement_with_prior_map.json 을 결과 디렉토리에 생성 → copyAlignmentToEfs 가 EFS 로 승격
  • 실제: scenemapper 는 실행됐으나 Grid map is not available or empty. Cannot calculate alignment quality. 경고를 남기고 해당 산출물을 생성하지 않은 채 정상 종료 → getFileSize <= 0 조건에 걸려 RefinerNotFoundInputFiles 로 job 실패 처리

Note: 다른 산출물 3종(capture_alignments_all.json, capture_alignments_sampled.json, align_preview.json)은 if 브랜치에서 logger.warn 만 남기고 넘어가는 반면, align_preview_meta_refinement_with_prior_map.json 하나만 throw 하도록 되어 있다. 이는 이 파일이 후속 단계(checkAndCopyForReconstructionavailable_json_for_reconstruction 호출 및 downstream reconstruction) 에서 필수 입력으로 사용된다고 추정되기 때문으로 보이지만, 코드 상 명시적 문서화는 없다 (uncertain -- needs verification).

Log Evidence#

Datadog 쿼리 (재현용):

Datadog querytext
service:cupixworks-capture-refinement-arm-instance @environment:production "not found refined align_preview_meta_refinement_with_prior_map.json"

핵심 에러 로그 원문 (raw attribute):

Datadog raw log — capture 734484 (job 1194920), 2026-07-14T06:38:17.718Zjson
{
  "stack": "Error: not found refined align_preview_meta_refinement_with_prior_map.json\n    at RefinementService.copyAlignmentToEfs (/tmp/agent/dist/app.cjs:7467:15)\n    at async RefinementService.run (/tmp/agent/dist/app.cjs:7210:11)\n    at async RefinementService.init (/tmp/agent/dist/app.cjs:7165:7)",
  "level": "error",
  "session": { "id": "4fdf37af58d3ef3843f0281770c366eb580eb1d5" },
  "capture": { "id": 734484 },
  "team": { "domain": "clark-vdc", "id": 87 },
  "job": { "id": 1194920 },
  "region": "us-west-2",
  "host": { "name": "4769d35ddbc5" },
  "@timestamp": "2026-07-14T06:38:17.718Z"
}
Datadog raw log — capture 734539 (job 1194919), 2026-07-14T06:37:45.182Zjson
{
  "stack": "Error: not found refined align_preview_meta_refinement_with_prior_map.json\n    at RefinementService.copyAlignmentToEfs (/tmp/agent/dist/app.cjs:7467:15)\n    at async RefinementService.run (/tmp/agent/dist/app.cjs:7210:11)\n    at async RefinementService.init (/tmp/agent/dist/app.cjs:7165:7)",
  "capture": { "id": 734539 },
  "team": { "domain": "clark-vdc" },
  "job": { "id": 1194919 },
  "host": { "name": "4e2b6d37118e" },
  "@timestamp": "2026-07-14T06:37:45.182Z"
}

동일 시간대 warn 시퀀스 (같은 인스턴스, copyAlignmentToEfs 함수 로그 그대로):

Datadog — preceding warn logstext
2026-07-14T06:36:59Z  warn   [124603.75] | Grid map is not available or empty. Cannot calculate alignment quality.
2026-07-14T06:38:17Z  warn   RefinementService::copyAlignmentToEfs | not found refined align_preview_meta_refinement_with_prior_map.json
2026-07-14T06:38:17Z  error  not found refined align_preview_meta_refinement_with_prior_map.json

같은 서비스에서 이 에러 메시지의 전체 14일 발생 이력 (직전 이틀):

14d history — 'not found refined align_preview_meta_refinement_with_prior_map.json'text
2026-07-13 23:46:09
2026-07-14 02:59:23
2026-07-14 03:42:08
2026-07-14 03:44:50
2026-07-14 06:37:01
2026-07-14 07:51:34

동일 서비스에서 관측된 관련 크래시 신호(scenemapper child process):

Related child-process errors (same service, same day)text
2026-07-14 12:05:50  error  Process killed by signal SIGSEGV (code: null)
2026-07-14 12:05:50  error  ChildProcessManager::setupEventHandlers | Child process exited
  • 이 에러는 클러스터의 2건 외에도 최근 이틀 동안 여러 번 반복되고 있으므로 일회성 이벤트가 아니라 재발성 패턴이다.
  • 동일 시간대 scenemapper SIGSEGV 도 관측되는 것으로 보아 refinement 파이프라인 자체의 안정성 이슈가 있는 것으로 보이지만, 이 클러스터의 두 이벤트에서 SIGSEGV 로그는 확인되지 않았다 (uncertain -- 두 사건이 같은 근본 원인인지는 별도 조사 필요).

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 Scenemapper 가 유효한 grid map 부재로 refinement 결과(align_preview_meta_refinement_with_prior_map.json) 를 생성하지 못했다 에러 발생 시점 인근에 scenemapper 의 [124603.75] Grid map is not available or empty. Cannot calculate alignment quality. warn 이 반복 출력됨. refinement-service.ts:372CPUtils.getFileSize(...) > 0 게이트가 false 로 떨어짐. Stack 이 copyAlignmentToEfs 로만 되어 있어 scenemapper 자체는 예외를 던지지 않고 종료 Confirmed
H2 Scenemapper child process 가 SIGSEGV 로 죽어 산출물을 남기지 못했다 같은 서비스에서 2026-07-14 12:05:50 에 Process killed by signal SIGSEGV 관측됨 이 클러스터의 두 이벤트 시간대(06:37-06:38)에는 SIGSEGV 로그가 없고, ScenemapperManager::executetry/catch 도 warn 을 남기지 않았음. 대신 Grid map is not available warn 이 정상적으로 출력됨 → child process 는 정상 종료 Rejected (for this cluster)
H3 alignment_archive.bin 등 입력 파일 자체가 없어서 실패 입력 파일이 없으면 checkInputFiles 에서 먼저 not found alignment_archive.bin 로 실패해야 하는데, 클러스터의 에러 메시지와 stack 이 copyAlignmentToEfs 로 확정됨 (refinement-service.ts:148-152 vs :381) Stack 이 checkInputFiles 를 거치지 않음 Rejected
H4 EFS 마운트/권한 문제로 파일 복사 실패 실패 지점은 EFS 로의 fs.copyFileSync 이전 단계인 로컬 파일 사이즈 체크(CPUtils.getFileSize(alignPreviewRefinementFileLocalPath)). 로컬 파일이 없다는 뜻이므로 EFS 관련 아님 Rejected
H5 코드 경로가 이 특정 파일 하나만 fatal 로 취급하는 게 과도한 게이팅이고, 실제로는 partial success 로 처리 가능 다른 3개 산출물은 동일 코드에서 warn 만 남기고 통과. 오직 이 파일만 throw (refinement-service.ts:378-382) 이 파일이 downstream reconstruction 판단(checkAndCopyForReconstructionavailable_json_for_reconstruction) 의 필수 입력일 가능성 있음(코드상 문서 없음) Inconclusive — 정책 결정 필요 (product/algorithm 팀 확인 대상)

Fix Recommendation#

즉시 조치 (Critical)#

  • 즉시 코드 변경은 없음. 이 두 캡처(734539, 734484)에 대해 refinement 를 재실행하거나 입력(selected_unrefined_cluster_id / 원본 alignment) 상태를 검토해 수동 재처리 필요.
  • clark-vdc 팀 관측: 최근 이틀 동안 동일 에러가 6건 이상 반복되고 있으므로 SRE / 3D reconstruction owner 에게 알림 채널로 공유 필요. (외부 조율 항목이므로 자동 code-fix 에서는 제외)

단기 개선 (1주 이내)#

  • 대상 파일: applications/agents/packages/cupix-capture-refinement-agent/src/refinement-service.ts:378-382
    • 관측 강화: 현재 logger.warn 은 파일명만 남기므로, scenemapper 가 남긴 마지막 Grid map ... warn 과 상관관계를 확인하려면 grep/조인이 필요하다. 실패 직전에 RefinementService::copyAlignmentToEfs | results file list - ... (line 344, debug 레벨) 를 warn 또는 info 로 승격하거나, 실패 시점에 결과 디렉토리의 파일 목록/사이즈를 error 레벨로 함께 출력하면 "산출물이 하나도 없음 vs 하나만 없음" 을 로그만으로 구분할 수 있다.
  • 대상 파일: applications/agents/packages/cupix-capture-refinement-agent/src/refinement-service.ts:378-382
    • 에러 코드 세분화: 현재 RefinerNotFoundInputFiles 코드는 checkInputFiles (입력 부재) 와 copyAlignmentToEfs (산출물 부재) 두 상황에 동시에 쓰이고 있다 (:150, :380, :426). 산출물 부재는 별도 코드(예: RefinerNoRefinementOutput) 로 분리해 downstream(tesla API) 이 재시도/스킵 정책을 다르게 적용할 수 있게 한다.
  • 대상 파일: applications/agents/packages/cupix-capture-refinement-agent/src/manager/scenemapper.manager.ts — child process 종료 코드 및 stdout tail 을 error 레벨로 캡처해 "정상 종료했지만 산출물 없음" 케이스의 원인(예: grid map 미생성) 을 사후 분석 가능하도록 개선.

장기 개선 (재발 방지)#

  • Scenemapper 알고리즘 팀과 조율하여 "grid map 미확보 → refinement 미생성" 시나리오가 정상 결과인지 이상 상태인지 판정 기준을 정의. 정상 결과라면 agent 는 throw 대신 job 을 no_refinement_available 로 종료하도록 정책 변경.
  • 재발성 패턴이므로 Datadog 모니터를 도입해 24h 동안 이 에러가 임계치(예: 5건) 초과 시 clark-vdc 팀과 3D reconstruction owner 에게 알림.

Monitoring#

REQUIRED SUB-SKILL: writing-datadog-monitoring-queries 규칙에 따라 timeseries widget 에 직접 사용 가능한 형태로 작성 (pipe/stats/count by 미사용).

  • 이 특정 에러의 발생 빈도 추이:
text
service:cupixworks-capture-refinement-arm-instance @environment:production "not found refined align_preview_meta_refinement_with_prior_map.json"
  • 선행 warn (grid map) 상관관계 관측:
text
service:cupixworks-capture-refinement-arm-instance @environment:production "Grid map is not available or empty"
  • 서비스 전반의 에러 볼륨(회귀 감지용):
text
service:cupixworks-capture-refinement-arm-instance status:error @environment:production
  • 관련된 scenemapper child process 크래시 관측:
text
service:cupixworks-capture-refinement-arm-instance @environment:production "Process killed by signal SIGSEGV"

Risk Assessment#

  • Risk level: medium — 클러스터 자체는 2건이지만 동일 에러가 최근 이틀 동안 여러 번 재발 중이며, 실패한 캡처는 후속 3D reconstruction 파이프라인이 진행되지 않아 사용자 산출물 지연으로 이어질 수 있다.
  • 예상 복잡도: standard — 로깅/에러코드 세분화는 pure-code 변경이며 refinement-service 파일 국지적 수정으로 가능. 다만 "throw 를 유지할지 partial success 로 완화할지" 정책 결정은 알고리즘/제품 팀 조율이 필요하므로 자동 code-fix 범위 밖으로 분류한다.