FileSystemManager::loadCPCaptureModel | end - not found file - /efs/54675fd9988271b9/preprocessor/re
RCA: FileSystemManager::loadCPCaptureModel | end - not found file
Overview#
What Happened#
2026-04-26 22:20:18 UTC에 cupixworks-capture-postprocessor-agent 서비스에서 EFS 상의 preprocessor 결과 파일(results.json)을 읽으려 했으나 파일이 존재하지 않아 실패했다. 이 에러는 EFS cleanup 프로세스가 postprocessor 실행 전에 preprocessor 결과 디렉토리를 삭제했기 때문에 발생했다. 동일 패턴이 3개의 서로 다른 capture ID에서 반복적으로 관찰되었다.
Quick Facts#
| Field | Value |
|---|---|
| exception.message | FileSystemManager::loadCPCaptureModel | end - not found file - /efs/54675fd9988271b9/preprocessor/results/results.json |
| top_frame | packages/cupix-capture-postprocessor-agent/src/manager/file-system.manager.ts:115 |
| env | production, us-west-2 |
Affected Teams#
| Team / Domain | Error Count | Impact |
|---|---|---|
| walmart | 5 | capture postprocessing 실패로 인해 캡처 결과물이 생성되지 않음. 재처리 필요. |
Timeline#
- 2026-04-26 07:14:45 UTC — capture
25506cb77b49cb41,75793cb1bbbceeffEFS CLEANUP 및 REMOVE 수행 - 2026-04-26 22:20:11 UTC — capture
54675fd9988271b9EFS CLEANUP 시작 - 2026-04-26 22:20:18 UTC — postprocessor가
54675fd9988271b9의results.json로드 시도 → 파일 없음 에러 (이 클러스터의 대표 에러) - 2026-04-26 22:20:48 UTC —
54675fd9988271b9EFS REMOVE 완료 - 2026-04-26 21:59:31–22:02:31 UTC —
25506cb77b49cb41,75793cb1bbbceeff에서 동일 에러 반복 발생 (이미 삭제된 디렉토리에 대한 재시도)
Error Log#
FileSystemManager::loadCPCaptureModel | end - not found file - /efs/54675fd9988271b9/preprocessor/results/results.json
Impact#
- Service:
cupixworks-capture-postprocessor-agent - Team: walmart
- 발생 횟수: 1 (이 클러스터 기준; 동일 패턴의 다른 capture 포함 시 최소 5건)
- 최초 발생: 2026-04-26T22:20:18.554Z
- 최근 발생: 2026-04-26T22:20:18.554Z
Root Cause Summary#
EFS cleanup 프로세스가 capture의 preprocessor 결과 디렉토리(/efs/{capture_id}/)를 삭제한 후에 postprocessor agent가 SQS 메시지를 수신하여 results.json 파일을 로드하려 시도했다. postprocessor는 preprocessor가 EFS에 기록한 results.json을 필수 입력으로 요구하지만, cleanup이 먼저 수행되어 파일이 존재하지 않았다. 이는 pipeline 단계 간 실행 순서가 보장되지 않는 설계 문제이다. 추가로, loadCPCaptureModel이 reject 시 에러 객체를 전달하지 않아 getApiErrorToDeleteMessage에서 Cannot read properties of undefined (reading 'response') 2차 에러가 발생한다.
Technical Analysis#
Code Path#
- Entry point:
postprocessor-service.ts:64—run()메서드가 SQS 메시지를 처리 postprocessor-service.ts:87-89—FileSystemManager를 생성하고 EFS 경로를 설정한 후loadCPCaptureModel()호출
const fileSystemManager = new FileSystemManager(Environment.DEBUG_MODE);
fileSystemManager.setErrorCode = (errorCode: string) => this.jobManager.setErrorCode(errorCode);
fileSystemManager.setEfsPath(cpCapture);
fileSystemManager.makeEfsDirectory();
await fileSystemManager.loadCPCaptureModel(cpCapture);
- Failure point:
file-system.manager.ts:114-116—CPUtils.getFileSize()가-1을 반환 (파일 없음)하여 에러 로그를 출력하고reject()
const preprocessorResultsFilePath = path.join(this.preProcessorDirPath, Constants.DefaultResultsDirName, Constants.DefaultCPCaptureJsonFileName);
if (CPUtils.getFileSize(preprocessorResultsFilePath) === -1) {
logger.error('FileSystemManager::loadCPCaptureModel | end - not found file - %s', preprocessorResultsFilePath);
return reject();
}
CPUtils.getFileSize()는fs.statSync()를 호출하고, 파일이 없으면-1을 반환:
static getFileSize = (filePath: string): number => {
try {
const stats = fs.statSync(filePath);
return stats ? stats.size : -1;
} catch (error) {
return -1;
- 2차 에러 경로:
reject()가 인자 없이 호출되어error가undefined로 전파됨 →base-service.ts:249에서error.response접근 시 TypeError 발생:
private getApiErrorToDeleteMessage = (error: any): any => {
if (error == undefined) {
logger.warn('BaseService::getApiErrorToDeleteMessage | undefined error');
return 'undefined error';
}
// ...
const response = CPUtils.isJsonString(error) ? JSON.parse(error) : error.response;
if (response == undefined) {
reject()가 인자 없이 호출되면 error는 undefined가 된다. error == undefined 체크(line 241)에서 걸려야 하지만, 실제로는 error가 빈 Promise rejection value로 전달되는 경우 이 체크를 통과할 수 있다. 로그에서 "Cannot read properties of undefined (reading 'response')" 에러가 동시에 발생한 것이 이를 뒷받침한다.
Log Evidence#
capture 54675fd9988271b9의 EFS 생명주기와 postprocessor 에러 타이밍:
Datadog query: "54675fd9988271b9" (status:error OR status:info) from:2026-04-26T20:00:00Z to:2026-04-27T00:00:00Z
2026-04-27 06:55:34 KST — QMJob::makeContainerOverride | capture_id=687714, EFS_PREPROCESSOR_PATH=/efs/54675fd9988271b9/preprocessor
2026-04-27 07:20:12 KST — EFS CLEANUP (path: /efs/54675fd9988271b9, size: 3.8G)
2026-04-27 07:20:13 KST — EFS CREATE_TSV (path: /efs/54675fd9988271b9/summary.tsv)
2026-04-27 07:20:14 KST — EFS COPY_TO_S3 (from: /efs/54675fd9988271b9/summary.tsv, to: cupix-tesla-efs-uswe2/production/54675fd9988271b9)
2026-04-27 07:20:18 KST — [ERROR] FileSystemManager::loadCPCaptureModel | end - not found file - /efs/54675fd9988271b9/preprocessor/results/results.json
2026-04-27 07:20:50 KST — EFS REMOVE (path: /efs/54675fd9988271b9)
핵심: EFS CLEANUP(07:20:12) 이후 6초 만에 postprocessor가 results.json을 읽으려 했으나(07:20:18), cleanup이 이미 preprocessor/results/ 디렉토리의 파일을 삭제한 상태였다.
capture 25506cb77b49cb41의 타이밍 — EFS가 이미 오래 전에 삭제된 후 postprocessor 재시도:
Datadog query: "25506cb77b49cb41" "EFS" from:2026-04-25T00:00:00Z to:2026-04-27T00:00:00Z
2026-04-26 16:14:46 KST — EFS CLEANUP (path: /efs/25506cb77b49cb41, size: 8.8G)
2026-04-26 16:16:23 KST — EFS REMOVE (path: /efs/25506cb77b49cb41)
2026-04-27 06:59:31 KST — [ERROR] FileSystemManager::loadCPCaptureModel | end - not found file (14시간+ 후 재시도)
2026-04-27 08:02:31 KST — [ERROR] FileSystemManager::loadCPCaptureModel | end - not found file (15시간+ 후 재시도)
SQS 메시지 재시도 패턴 — ApproximateReceiveCount가 증가하며 반복 실패:
{
"error": "undefined error",
"sqsMessage": {
"MessageId": "e968d567-8fdb-4d4b-97fe-5d592f825aad",
"Attributes": { "ApproximateReceiveCount": "2" }
}
}
2차 에러 — reject() 인자 미전달로 인한 TypeError:
Datadog query: service:cupixworks-capture-postprocessor-agent "Cannot read properties of undefined" "response" from:2026-04-26T21:00:00Z to:2026-04-26T23:30:00Z
2026-04-27 08:02:31 KST — Cannot read properties of undefined (reading 'response')
2026-04-27 08:02:30 KST — Cannot read properties of undefined (reading 'response')
2026-04-27 06:59:33 KST — Cannot read properties of undefined (reading 'response')
2026-04-27 06:59:31 KST — Cannot read properties of undefined (reading 'response')
이 에러들은 loadCPCaptureModel의 reject() 에러와 항상 같은 시각에 발생한다.
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | EFS cleanup이 postprocessor 실행 전에 preprocessor 결과를 삭제하여 results.json이 존재하지 않음 | 54675fd9988271b9: EFS CLEANUP 07:20:12 → error 07:20:18 (6초 차이). 25506cb77b49cb41: REMOVE 전날 16:16 → error 다음날 06:59/08:02. 3개 capture 모두 동일 패턴 |
— | Confirmed |
| H2 | Preprocessor가 results.json 생성에 실패하여 파일이 원래 없었음 | preprocessor 에러 로그 없음, 54675fd9988271b9는 이전 실행(04-25)에서 정상 동작 (loadSkatResults warn만 있음) |
EFS CLEANUP 로그가 존재하고, capture 54675fd9988271b9의 EFS 크기가 3.8G로 데이터가 존재했음을 확인 |
Rejected |
| H3 | EFS 마운트 또는 파일시스템 오류로 인한 일시적 접근 불가 | — | 3개 capture 모두에서 일관되게 발생하고, EFS REMOVE 로그가 명확하게 디렉토리 삭제를 확인 | Rejected |
Fix Recommendation#
즉시 조치 (Critical)#
file-system.manager.ts:116—reject()호출 시 에러 객체를 전달하도록 수정. 현재reject()가 인자 없이 호출되어BaseService::getApiErrorToDeleteMessage에서 2차 TypeError 발생.reject(new Error('results.json not found: ' + preprocessorResultsFilePath))와 같이 의미 있는 에러를 전달해야 한다.- 동일 파일의 다른
reject()호출(line 88,line 110,line 133)도 동일하게 에러 객체 미전달 문제가 있으므로 함께 수정.
단기 개선 (1주 이내)#
- Pipeline orchestration 검토: postprocessor SQS 메시지가 발송되는 시점과 EFS cleanup 시점 간의 순서를 보장하는 메커니즘 확인. Cleanup이 postprocessor 완료 후에만 수행되도록 job 상태 확인 로직 추가 필요.
loadCPCaptureModel에서 EFS 디렉토리 자체의 존재 여부를 먼저 확인하고, 디렉토리가 없는 경우 "EFS directory already cleaned up" 등 더 명확한 에러 메시지를 제공하여 진단을 용이하게 함.
장기 개선 (재발 방지)#
- EFS lifecycle과 processing pipeline 간의 결합도를 낮추는 설계 필요. Job 상태 머신에
cleanup단계를 명시적으로 추가하여, 모든 downstream agent(postprocessor)의 완료를 확인한 후에만 cleanup을 수행하도록 해야 한다. - EFS cleanup 전에 해당 capture에 대한 pending SQS 메시지가 있는지 확인하거나, cleanup 완료 후 관련 SQS 메시지를 삭제하는 로직 추가.
Monitoring#
- 추가할 메트릭:
loadCPCaptureModel실패 횟수를 별도 커스텀 메트릭으로 추적 - Datadog 쿼리:
service:cupixworks-capture-postprocessor-agent status:error "loadCPCaptureModel" "not found file"
- EFS cleanup과 postprocessor 에러의 상관관계 알림:
service:cupixworks-capture-postprocessor-agent ("EFS CLEANUP" OR "EFS REMOVE" OR "loadCPCaptureModel")
Risk Assessment#
- Risk level: medium
- 예상 복잡도: standard — reject() 에러 전달은 trivial하나, pipeline ordering 수정은 EFS cleanup 로직과 job orchestration 전체를 이해해야 함