[CupixAerialMap] preprocess fail {"message":"Endpoint request timed out"}
RCA: [CupixAerialMap] preprocess fail - Endpoint request timed out
Overview#
What Happened#
2026-04-21 eu-central-1 리전에서 aerial-map-service의 preprocess 단계가 Pix4D Cloud API 호출 중 {"message":"Endpoint request timed out"} 에러로 2회 실패했다. 동일 tenant(cupix)의 동일 팀(rakentava)에서 연속으로 요청한 aerial map ID 24(oblique)와 25(nadir)가 모두 영향을 받았다.
Quick Facts#
| Field | Value |
|---|---|
| exception.message | {"message":"Endpoint request timed out"} |
| top_frame | src/preprocess/index.ts:148 |
| runtime | Node.js 20 on ECS Fargate (1024 CPU, 2048 MB) |
| deploy | cupix-aerial-map-preprocess:prod (sha256:4e7e2be7a3bb) |
| env | production, eu-central-1 |
Affected Teams#
| Team / Domain | Error Count | Impact |
|---|---|---|
| rakentava | 2 | Aerial map ID 24, 25의 preprocess 실패. 사용자의 드론 사진 처리가 완료되지 않음 |
Timeline#
- 09:49:56 UTC — Aerial map 24 (oblique) navigate → preprocess 시작
- 09:50:58 UTC — Pix4D project 생성 완료
- 09:51:27 UTC — Pix4D API 호출 중 "Endpoint request timed out" 에러 발생 (첫 번째 실패)
- 09:52:23 UTC — preprocess-check Lambda: States.TaskFailed 확인, process-fail 처리
- 10:05:16 UTC — Aerial map 25 (nadir) navigate → preprocess 시작
- 10:06:13 UTC — Pix4D project 생성 완료
- 10:08:43 UTC — configProcessing 완료 (horizontal_crs: 32635)
- 10:09:12 UTC —
startProcessing호출 중 "Endpoint request timed out" 에러 발생 (두 번째 실패) - 10:10:09 UTC — preprocess-check Lambda: States.TaskFailed 확인, process-fail 처리
Error Log#
[CupixAerialMap] preprocess fail {"message":"Endpoint request timed out"}
Impact#
- Service:
aerial-map-service - 발생 횟수: 2
- 최초 발생: 2026-04-21T09:51:27.709Z
- 최근 발생: 2026-04-21T10:09:12.790Z
Root Cause Summary#
Pix4D Cloud API(PIX4D_ENDPOINT)가 AWS API Gateway 뒤에서 동작하며, API Gateway의 기본 통합 타임아웃(29초) 내에 Pix4D 백엔드가 응답하지 못해 504 {"message":"Endpoint request timed out"} 에러가 반환되었다. aerial-map-service의 axios 클라이언트는 5xx 에러에 대해 최대 3회 재시도하지만, Pix4D 백엔드 자체의 지연(과부하 또는 일시적 장애)으로 인해 재시도 역시 동일하게 타임아웃되어 최종 실패하였다. 두 건의 에러는 동일 팀의 연속 요청에서 ~18분 간격으로 발생하여, Pix4D 측 일시적 서비스 저하가 원인으로 판단된다.
Technical Analysis#
Code Path#
- Entry point:
src/preprocess/index.ts:156— CLI 입력 파싱 후app(input)호출 - 실행 흐름:
cupixApi.saveProcessingState()— Cupix API에 "preprocessing" 상태 저장cupixApi.getAerialPhotosByAerialMapId()— 사진 목록 조회downloadStreamByUrl()+readPhotoExif()— 첫 사진 EXIF 읽기cupixApi.saveCameraAndImageInfo()— 카메라 정보 저장pix4dApi.createPix4dProject()— Pix4D 프로젝트 생성 (로그에서 성공 확인)pix4dApi.getPix4dS3Credential()— S3 자격증명 획득- 사진 다운로드/업로드 루프 (p-limit 10 동시)
pix4dApi.registerPix4dImages()— 이미지 벌크 등록pix4dApi.registerGcps()— GCP 등록 (없으면 skip)cupixApi.getAerialMap()— CRS 정보 조회pix4dApi.configProcessing()— 처리 옵션 설정pix4dApi.startProcessing()— 처리 시작 요청 (Failure point)
} catch (error: any) {
if (error instanceof AerialMapError) {
await cupixApi.saveError(aerialMapId, error.code, error.reason);
} else {
logger.error(`[CupixAerialMap] preprocess fail ${error.message}`);
await cupixApi.saveError(aerialMapId, ERROR_CODE['AMB710'].code, ERROR_CODE['AMB710'].reason);
}
throw error;
}
error.message가 {"message":"Endpoint request timed out"}인 이유: Pix4D API 클래스의 catch 블록에서 throw new Error(JSON.stringify(error.response?.data || error.message))로 에러를 재생성하기 때문. API Gateway의 504 응답 body가 그대로 error message에 포함된다.
async startProcessing(projectId: number) {
try {
console.log(`[CupixApi-Pix4d] startProcessing - /project/api/v3/projects/${projectId}/start_processing`);
const response = await axios.post(
`${this._endpoint}/project/api/v3/projects/${projectId}/start_processing`,
{},
{ headers: { Authorization: `Bearer ${this._accessToken}` } },
);
return response.data;
} catch (error: any) {
console.error(
`[CupixApi-Pix4d] startProcessing - /project/api/v3/projects/${projectId}/start_processing - ${error.message}`,
);
throw new Error(JSON.stringify(error.response?.data || error.message));
}
}
- Axios 클라이언트 설정: timeout 60초, 5xx 에러 시 최대 3회 재시도 (지수 백오프: 1s, 2s, 4s)
const RETRY_CODES = ['ECONNRESET', 'ETIMEDOUT', 'ECONNABORTED', 'EAI_AGAIN'];
const MAX_RETRIES = 3;
const BASE_DELAY_MS = 1000;
const REQUEST_TIMEOUT_MS = 60000;
const axios = _axios.create({
timeout: REQUEST_TIMEOUT_MS,
});
- Occurrence 1 (aerial map 24):
createPix4dProject성공 후 ~29초 뒤 실패.configProcessing로그가 없으므로 사진 업로드 또는registerPix4dImages단계에서 Pix4D API 타임아웃 발생 추정 - Occurrence 2 (aerial map 25):
configProcessing성공 후 정확히 29초 뒤 실패.startProcessing호출에서 Pix4D API Gateway 타임아웃 발생 확정
Log Evidence#
검색 쿼리:
service:aerial-map-service status:error
Time range: 2026-04-21T08:50:00Z to 2026-04-21T10:40:00Z
service:aerial-map-service
Time range: 2026-04-21T09:40:00Z to 2026-04-21T10:20:00Z (ascending)
Occurrence 1 (aerial map 24) 로그 타임라인:
18:50:58 KST [CupixAerialMap] create pix4d project - project name: cupix-production-rakentava-24-1776765058394
18:51:27 KST [CupixAerialMap] preprocess fail {"message":"Endpoint request timed out"}
18:51:27 KST [CupixAerialMap] preprocess fail - error:({}) / message:({"message":"Endpoint request timed out"})
프로젝트 생성과 에러 사이 29초. configProcessing 로그가 없으므로 그 이전 Pix4D API 호출에서 실패.
Occurrence 2 (aerial map 25) 로그 타임라인:
19:06:13 KST [CupixAerialMap] create pix4d project - project name: cupix-production-rakentava-25-1776765973348
19:08:43 KST [CupixAerialMap] No GCPs provided, proceeding without GCP registration
19:08:43 KST [CupixAerialMap] configProcessing - horizontal_crs: 32635, vertical_crs: 3900, geoid_model: FIN2023N2000, geoid_height: null
19:09:12 KST [CupixAerialMap] preprocess fail {"message":"Endpoint request timed out"}
19:09:12 KST [CupixAerialMap] preprocess fail - error:({}) / message:({"message":"Endpoint request timed out"})
configProcessing과 에러 사이 정확히 29초 — startProcessing 호출에서 API Gateway 504 타임아웃.
ECS Task 정보 (preprocess-check Lambda에서 확인):
{
"StopCode": "EssentialContainerExited",
"StoppedReason": "Essential container in task exited",
"ExitCode": 1,
"StartedBy": "AWS Step Functions",
"LaunchType": "FARGATE",
"Cpu": "1024",
"Memory": "2048"
}
No warn-level logs — service:aerial-map-service status:warn 검색에서 0건. Axios 재시도 warn 로그([AerialMap] Request failed ...retrying)가 없다는 것은 재시도가 발생하지 않았거나, 504 응답이 retryable 조건에 매칭되지 않았을 가능성을 시사한다. 그러나 코드상 error.response.status >= 500 체크가 있으므로 504는 재시도 대상이다. warn 로그가 Datadog에 없는 이유는 console.warn이 Datadog에서 info 레벨로 수집될 수 있기 때문이다 — uncertain, needs verification.
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | Pix4D Cloud API Gateway 타임아웃 (29초) — Pix4D 백엔드 지연 | 에러 메시지 {"message":"Endpoint request timed out"}는 AWS API Gateway 504 응답의 표준 포맷. occurrence 2에서 configProcessing → error 간격이 정확히 29초 |
— | Confirmed |
| H2 | Cupix API (CUPIX_ENDPOINT) CloudFront 타임아웃 |
CloudFront origin_read_timeout = 60초 (infra 코드 확인). CloudFront 504 에러는 HTML 형식이지 JSON {"message":...} 형식이 아님 |
Cupix API는 CloudFront 뒤에 있으며 60초 타임아웃. 에러 형식이 API Gateway JSON과 일치하지 않음 | Rejected |
| H3 | Axios 클라이언트 자체 타임아웃 (60초) | REQUEST_TIMEOUT_MS = 60000 설정 |
에러 메시지가 timeout of 60000ms exceeded가 아닌 {"message":"Endpoint request timed out"}. 간격이 60초가 아닌 29초 |
Rejected |
| H4 | 네트워크 연결 문제 (ECONNRESET 등) | — | 에러 코드가 ECONNRESET/ETIMEDOUT이 아닌 504 응답 body. error:({}) — error 객체가 빈 JSON으로 serialize됨 (Error 객체의 enumerable properties가 없음) |
Rejected |
| H5 | ECS Fargate 리소스 부족으로 인한 처리 지연 | Fargate memory 2048MB, CPU 1024 | 에러가 외부 API 호출(Pix4D)에서 발생. Fargate 내부 연산이 아닌 HTTP 응답 타임아웃. 메모리 사용량도 정상 | Rejected |
Fix Recommendation#
즉시 조치 (Critical)#
- 없음. Pix4D 외부 서비스의 일시적 지연이 원인이므로 aerial-map-service 코드 자체에 즉각적인 버그 수정은 불필요하다. 현재 에러 발생 시
process-failLambda가 정상적으로 실패 처리하고 있다.
단기 개선 (1주 이내)#
- Pix4D API 호출 재시도 로직 강화:
src/code/src/common/axios.ts의MAX_RETRIES를 3에서 5로 늘리고,BASE_DELAY_MS를 더 길게 설정(예: 3000ms)하여 Pix4D 백엔드 복구 시간을 확보한다. 특히startProcessing같은 중요 API 호출에 대해 별도의 긴 재시도 정책을 적용하는 것을 고려한다. - 에러 메시지 개선:
src/code/src/common/api.ts의 각 Pix4D API 메서드에서 catch 시 어떤 endpoint에서 타임아웃이 발생했는지 명확히 로깅한다. 현재는error.message만 기록되어 어떤 API 호출이 실패했는지 로그만으로 특정하기 어렵다. - Pix4D API 응답 코드 로깅: axios interceptor의 warn 로그에
error.response?.status를 추가하여 재시도 발생 여부와 HTTP 상태 코드를 추적할 수 있도록 한다.
장기 개선 (재발 방지)#
- 자동 재처리(retry) 메커니즘: Step Functions 워크플로에 preprocess 실패 시 자동 재시도 로직 추가. 현재는 실패 → process-fail로 바로 이동하지만, 일시적 타임아웃의 경우 일정 시간 후 재시도하면 성공할 가능성이 높다.
- Pix4D API 상태 모니터링: Pix4D Cloud API의 응답 시간과 에러율을 Datadog에서 모니터링하여, Pix4D 측 성능 저하를 조기에 감지한다.
Monitoring#
- Pix4D API 타임아웃 에러 발생 빈도 모니터링:
service:aerial-map-service "Endpoint request timed out" status:error
- Pix4D API 호출 지연 시간 추적 (axios interceptor에 메트릭 추가 필요):
avg:aerial_map.pix4d_api.response_time{endpoint:start_processing}
Risk Assessment#
- Risk level: low
- 예상 복잡도: trivial
- Pix4D 외부 서비스의 일시적 지연이며, 동일 팀의 연속 2건만 영향 받음. 시스템 전반에 대한 구조적 문제가 아닌 외부 의존성 타임아웃으로, aerial-map-service 코드의 재시도 강화로 완화 가능하다.