EfsManager::copyTo | end - {"errno":-2,"code":"ENOENT","syscall":"copyfile","path":"/tmp/workspace/6
RCA: EfsManager::copyTo ENOENT on alignment_archive.bin
Error Log#
EfsManager::copyTo | end - {"errno":-2,"code":"ENOENT","syscall":"copyfile","path":"/tmp/workspace/67246/results/alignment_archive.bin","dest":"/efs/753b0e42ed4cfcc7/skatmaster/results/alignment_archive.bin"}
Impact#
- Service:
cupixworks-captue-skatmaster-arm-instance - Team: built
- 발생 횟수: 21
- 최초 발생: 2026-04-06T09:24:20.529Z
- 최근 발생: 2026-04-07T09:19:14.478Z
Root Cause Summary#
SceneMapper(skat) 프로세스가 완료된 후, copyAlignPreviewFilesToSkatMasterResult() 메서드가 alignment_archive.bin 파일을 결과 디렉토리에서 EFS로 복사하려고 시도합니다. 그러나 SceneMapper SDK가 모든 실행에서 alignment_archive.bin을 생성하는 것은 아닙니다 — 이 파일은 align preview 기능이 활성화되고 정상적으로 처리된 경우에만 생성됩니다. copyAlignPreviewFilesToSkatMasterResult() 메서드는 파일 존재 여부를 확인하지 않고 fs.copyFileSync()를 바로 호출하기 때문에, 파일이 없으면 ENOENT 에러가 발생합니다. 이 에러는 catch 블록에서 잡혀 warn 레벨로 로깅되고 false를 반환하므로 프로세스 자체는 중단되지 않지만, EfsManager::copyTo에서 logger.error()로 먼저 기록되어 에러 클러스터로 수집됩니다.
Technical Analysis#
Code Path#
- Entry point:
skatmaster-service.ts:58—runSkatMaster()호출 skatmaster.manager.ts:204— SceneMapper 프로세스 실행 (this.execute(params))skatmaster.manager.ts:206-208—saveSkatMasterResults()호출 (alignment JSON 결과 저장, 성공)- Failure point:
skatmaster.manager.ts:209—copyAlignPreviewFilesToSkatMasterResult()호출
copyAlignPreviewFilesToSkatMasterResult() 메서드는 resultDirPath에서 세 파일(alignment_archive.bin, align_preview_default.png, align_preview_meta_default.json)을 EFS로 복사합니다. 파일 존재 여부 확인 없이 바로 copyTo()를 호출합니다:
// skatmaster.manager.ts:497-518
copyAlignPreviewFilesToSkatMasterResult = async (): Promise<boolean> => {
if (this.resultDirPath == undefined) {
logger.warn('SkatmasterManager::copyAlignPreviewFilesToSkatMasterResult | undefined results directory path');
return false;
}
try {
const fileList = await CPUtils.getFiles(this.resultDirPath);
logger.debug('...results file list - %s', JSON.stringify(fileList));
const binFilePath = path.join(this.resultDirPath, Constants.DefaultAlignPreviewBinFileName);
this.efsManager.copyTo(binFilePath, path.join(this.efsManager.skatMasterResultPath, Constants.DefaultAlignPreviewBinFileName));
// ... image, json 파일도 동일하게 복사
return true;
} catch (e) {
logger.warn('...exception occurred while copy align preview files to efs. error: %s', JSON.stringify(e));
return false;
}
};
copyTo() 메서드는 fs.copyFileSync()를 감싸는 래퍼로, 소스 파일이 없으면 ENOENT를 throw합니다:
// efs.manager.ts:40-51
copyTo = (source: string, target: string): void => {
try {
logger.debug('EfsManager::copyTo | source: %s, target: %s, fileSize: %s', source, target, CPUtils.formatBytesString(CPUtils.getFileSize(source)));
const start = new Date().getTime();
fs.copyFileSync(source, target);
const durationTime = new Date().getTime() - start;
logger.debug('EfsManager::copyTo | done - duration time: %d milliseconds', durationTime);
} catch(e) {
logger.error('EfsManager::copyTo | end - %s', JSON.stringify(e)); // <-- 에러 로그 발생 지점
throw e;
}
};
비교: saveSkatMasterResults() (efs.manager.ts:90-119)와 copyProcessOutputToEFS() (efs.manager.ts:121-146)에서는 fs.existsSync()로 파일 존재 여부를 먼저 확인하고 없으면 경고 후 건너뜁니다. copyAlignPreviewFilesToSkatMasterResult()에만 이 확인이 누락되어 있습니다.
// efs.manager.ts:131-134 — copyProcessOutputToEFS의 파일 존재 확인 (올바른 패턴)
if (!fs.existsSync(sourcePath)) {
logger.warn('EfsManager::copyProcessOutputToEFS | source does not exists %s', sourcePath);
isAllCopied = false;
continue;
}
Log Evidence#
Datadog에서 사용한 쿼리:
service:cupixworks-captue-skatmaster-arm-instance status:error "EfsManager::copyTo"
에러 로그 패턴 — 모든 21건이 동일한 패턴 (alignment_archive.bin의 ENOENT):
{
"timestamp": "2026-04-07 18:19:14 KST",
"status": "error",
"message": "EfsManager::copyTo | end - {\"errno\":-2,\"code\":\"ENOENT\",\"syscall\":\"copyfile\",\"path\":\"/tmp/workspace/676194/results/alignment_archive.bin\",\"dest\":\"/efs/cfb6084d36428188/skatmaster/results/alignment_archive.bin\"}"
}
{
"timestamp": "2026-04-07 14:14:22 KST",
"status": "error",
"message": "EfsManager::copyTo | end - {\"errno\":-2,\"code\":\"ENOENT\",\"syscall\":\"copyfile\",\"path\":\"/tmp/workspace/40329/results/alignment_archive.bin\",\"dest\":\"/efs/5e0ade3c1b90a87f/skatmaster/results/alignment_archive.bin\"}"
}
에러 직후 warn 로그 — copyAlignPreviewFilesToSkatMasterResult의 catch 블록과 runSkatMaster의 경고가 동일 타임스탬프에 기록됨:
service:cupixworks-captue-skatmaster-arm-instance "copyAlignPreviewFilesToSkatMasterResult"
{
"timestamp": "2026-04-07 18:19:14 KST",
"status": "warn",
"message": "SkatmasterManager::copyAlignPreviewFilesToSkatMasterResult | exception occurred while copy align preview files to efs. error: {\"errno\":-2,\"code\":\"ENOENT\",\"syscall\":\"copyfile\",\"path\":\"/tmp/workspace/676194/results/alignment_archive.bin\",\"dest\":\"/efs/cfb6084d36428188/skatmaster/results/alignment_archive.bin\"}"
}
service:cupixworks-captue-skatmaster-arm-instance "fail to copy align preview"
{
"timestamp": "2026-04-07 18:19:14 KST",
"status": "warn",
"message": "SkatmasterManager::runSkatMaster | fail to copy align preview files"
}
프로세스 전체는 정상 완료 — saveSkatMasterResults | write done과 runSkatMaster | done 로그가 동일 세션에서 확인됨:
{
"timestamp": "2026-04-07 18:36:49 KST",
"status": "info",
"message": "SkatmasterManager::saveSkatMasterResults | write done"
}
ChildProcessManager::setupEventHandlers | Child process exited 에러도 동시에 다수 발생하며, SceneMapper 프로세스 종료 시 일부 실행에서 align preview 파일이 생성되지 않는 것으로 보입니다.
Fix Recommendation#
즉시 조치 (Critical)#
- 파일:
skatmaster.manager.ts:507-512(copyAlignPreviewFilesToSkatMasterResult메서드) efsManager.copyTo()호출 전에fs.existsSync()체크를 추가하여, 파일이 없으면 warn 로그를 남기고 건너뛰도록 변경- 이미 같은 코드베이스의
copyProcessOutputToEFS()(efs.manager.ts:131-134)에 동일한 패턴이 구현되어 있으므로, 이 패턴을 따르면 됨 - 이렇게 하면
EfsManager::copyTo에서logger.error()가 호출되지 않아 에러 클러스터가 발생하지 않음
단기 개선 (1주 이내)#
alignment_archive.bin이 생성되지 않는 조건을 SceneMapper SDK 문서 또는 팀과 확인하여, 해당 파일이 선택적 출력물(optional output)인지 확인- 선택적 출력물이 맞다면,
copyAlignPreviewFilesToSkatMasterResult()전체를 선택적 복사 로직으로 재구성 (각 파일별 존재 확인 후 복사)
장기 개선 (재발 방지)#
copyTo()메서드에 optional 파라미터를 추가하여, 소스 파일이 없을 때 에러 대신 warn을 남기고false를 반환하는 모드를 지원하는 것을 고려- 또는
copyToIfExists()유틸리티 메서드를 추가하여, 선택적 파일 복사 시 일관된 패턴을 사용
Monitoring#
- 수정 후 에러 클러스터 재발 모니터링:
service:cupixworks-captue-skatmaster-arm-instance status:error "EfsManager::copyTo" "alignment_archive.bin"
- align preview 파일 미생성 빈도 추적 (warn 레벨):
service:cupixworks-captue-skatmaster-arm-instance "fail to copy align preview files"
Risk Assessment#
- Risk level: low
- 예상 복잡도: trivial
- 이 에러는 프로세스 중단을 일으키지 않으며 (
catch블록에서false반환 후 계속 진행), align preview 파일은 후속 처리(refinement, postprocessor)에서도 선택적으로 사용됨. 수정은fs.existsSync()한 줄 추가 수준으로 간단함.