DerivativesApi unsupported region maps to undefined URL
RCA: BaseService::handlingMessageErrors - Forge API Thumbnail 404
Overview#
What Happened#
2026-05-08 01:17~01:48 UTC 동안 cupixworks-any-thumbnail-agent 서비스에서 Autodesk Forge Model Derivative API로 BIM 썸네일 다운로드 요청 시 404 에러가 발생했다. API 요청 URL에 undefined가 포함되어 잘못된 경로로 요청이 전송되었으며, SQS 메시지가 최대 재시도 횟수(10회)에 도달한 후 삭제되면서 error 상태로 기록되었다.
Quick Facts#
| Field | Value |
|---|---|
| exception.class | AxiosError |
| exception.message | Request failed with status code 404 |
| top_frame | cpbim.ts:79 (catch block in downloadOriginal) |
| env | production, ap-southeast-2 |
Affected Teams#
| Team / Domain | Error Count | Impact |
|---|---|---|
| fluor (team_id: 142) | 4 | BIM 썸네일 생성 실패, BIM 모델 error 상태 전환 |
Timeline#
- 2026-05-08T01:17:36Z — 최초 에러 발생 (BIM ID 2976, user 5091)
- 2026-05-08T01:18:34Z — 동일 메시지 ApproximateReceiveCount=10 도달, SQS 메시지 삭제
- 2026-05-08T01:48:46Z — 마지막 에러 발생 (3건 추가 BIM 모델)
- 2026-05-08 — Error Sweeper가 클러스터 감지
Error Log#
BaseService::handlingMessageErrors | Error and message object - {"sqsMessage":{"MessageId":"18a53bf8-3eb3-4dd6-ab86-e1cd4b9bdb00","Attributes":{"ApproximateReceiveCount":"10"}}}
Impact#
- Service:
cupixworks-any-thumbnail-agent - 발생 횟수: 4 (10건 이상의 관련 로그 — 각 메시지가 10회 재시도)
- 최초 발생: 2026-05-08T01:18:34.621Z
- 최근 발생: 2026-05-08T01:48:46.768Z
Root Cause Summary#
forge-apis 라이브러리 (v0.9.10/v0.9.12)의 DerivativesApi가 BIM 모델의 forge_region 값을 URL 경로 prefix로 변환할 때, 지원하지 않는 region 값(ANZ/APAC 등)을 받으면 내부 region-to-path 매핑에서 undefined를 반환한다. 이로 인해 https://developer.api.autodesk.com/undefined/designdata/{urn}/thumbnail 형태의 잘못된 URL이 생성되어 Autodesk API에서 404를 반환한다. 정상적인 URL은 https://developer.api.autodesk.com/modelderivative/v2/designdata/{urn}/thumbnail (US region) 이어야 한다.
Technical Analysis#
Code Path#
- Entry point:
base-service.ts:108—runByMessages()호출 thumbnail-service.ts→cpbim.ts:20(setModel) — BIM 데이터 로드 및 Forge 인증cpbim.ts:45(downloadOriginal) — 썸네일 다운로드 시작cpbim.ts:48—forgeRegion결정cpbim.ts:59-61—DerivativesApi인스턴스 생성 (region 전달)cpbim.ts:68—getThumbnail()API 호출- Failure point:
cpbim.ts:78-79— 404 에러 catch base-service.ts:290—handlingMessageErrors호출base-service.ts:285—receiveCount >= MaxReceiveCount(10)판정 → 메시지 삭제
downloadOriginal = (): Promise<void> => new Promise((resolve, reject) => {
const serverModel = this._serverModel;
const forgeUrn = serverModel && (<any>serverModel).forge_urn;
const forgeRegion = serverModel && (<any>serverModel).forge_region ? serverModel.forge_region : Environment.ADF_REGION;
// ...
const derivativesApi = new FORGE.DerivativesApi(
undefined, forgeRegion
);
// ...
derivativesApi.getThumbnail(forgeUrn, { width: 400, height: 400}, this._oAuth2TwoLegged, this._oAuth2TwoLegged.getCredentials())
.then(res => { /* ... */ })
.catch(ec => {
logger.error('CPBim::downloadOriginal | end - %s', JSON.stringify(ec));
reject(ec);
});
});
forge-apis 라이브러리 내부에서 region 값을 API base path로 변환하는 매핑:
"US"→"modelderivative/v2"(정상 동작)"EMEA"→"modelderivative/v2/regions/eu"(정상 동작)- 기타 값 →
undefined(매핑 실패)
private handlingMessageErrors = async (error: any): Promise<void> => {
const errorAndMessage = { error: error, sqsMessage: {} };
if (this.messageInProcess) {
errorAndMessage.sqsMessage = {
MessageId: this.messageInProcess.MessageId,
Attributes: this.messageInProcess.Attributes
};
const apiErrorObject = this.getApiErrorToDeleteMessage(error);
if (apiErrorObject != undefined || this.checkReceiveCountToDeleteMessage()) {
try {
errorAndMessage.error = apiErrorObject;
await this.deleteByMessage(this.messageInProcess);
if (this._modelInProcess != undefined && this._modelInProcess.id > 0) await this.updateErrorState(this._modelInProcess);
} catch (error) {
logger.error('BaseService::handlingMessageErrors | Errors in error handling', error);
}
}
}
logger.error('BaseService::handlingMessageErrors | Error and message object - %s', JSON.stringify(errorAndMessage));
};
getApiErrorToDeleteMessage에서 AxiosError의 response가 undefined이므로 (error.response가 없음 — AxiosError의 config에만 정보가 있음) 빈 객체 {}가 warn 로그로 출력되었고, checkReceiveCountToDeleteMessage()가 receiveCount(10) >= MaxReceiveCount(10) 조건으로 true를 반환하여 메시지가 삭제되었다.
Log Evidence#
사용한 Datadog 쿼리:
service:cupixworks-any-thumbnail-agent status:error "CPBim::downloadOriginal"
핵심 에러 로그 — 잘못된 URL 확인:
{
"message": "CPBim::downloadOriginal | end - {\"message\":\"Request failed with status code 404\",\"name\":\"AxiosError\",\"config\":{\"method\":\"get\",\"url\":\"https://developer.api.autodesk.com/undefined/designdata/dXJuOmFkc2sud2lwcHJvZGFuejpmcy5maWxlOnZmLnNwQUdnVFduUnR1M2RYbWJPRW9jZ2c_dmVyc2lvbj04/thumbnail\",\"params\":{\"width\":\"400\",\"height\":\"400\"}},\"code\":\"ERR_BAD_REQUEST\",\"status\":404}",
"timestamp": "2026-05-08T01:48:46.740Z",
"meta": {"Bim": {"id": 2976}, "team": {"domain": "fluor", "id": 142}, "user": {"id": 5091}}
}
URL에서 /undefined/designdata/ 부분이 핵심 증거: modelderivative/v2 대신 undefined가 삽입됨.
에러 직전 warn 로그 — getApiErrorToDeleteMessage 빈 응답:
BaseService::getApiErrorToDeleteMessage | error msg - {}
에러 직후 info 로그 — 메시지 삭제 확인:
AwsQueueManager::deleteMessage | begin - queue url: https://sqs.ap-southeast-2.amazonaws.com/002596530511/cupix-tesla-thumbnail-agent-production
AwsQueueManager::deleteMessage | end - message id: aacbb970-61cc-4efe-9635-ce7173059645
다양한 URN prefix 확인 (모두 동일한 /undefined/ 경로 패턴):
dXJuOmFkc2sud2lwcHJvZGFueg—urn:adsk.wiprodanz(ANZ region)dXJuOmFkc2sud2lwczVqa3U—urn:adsk.wips5jkudXJuOmFkc2sud2lwczl2a2Q—urn:adsk.wips9vkddXJuOmFkc2sud2lwczJuZmw—urn:adsk.wips2nfldXJuOmFkc2sud2lwc2EzZjc—urn:adsk.wipsa3f7dXJuOmFkc2sud2lwczdid2M—urn:adsk.wips7bwc
이 URN들은 Autodesk의 다양한 region shard에 존재하는 파일들이며, forge-apis 라이브러리가 해당 region을 URL prefix로 변환하지 못하는 것이 공통 원인이다.
Hypotheses Considered#
| # | Hypothesis | Evidence for | Evidence against | Verdict |
|---|---|---|---|---|
| H1 | forge-apis 라이브러리가 BIM의 forge_region 값을 URL prefix로 변환 시 지원하지 않는 region 값에 대해 undefined를 반환 |
모든 에러 URL이 /undefined/designdata/ 패턴. 에러가 ap-southeast-2 region에서만 발생. 다양한 URN(다양한 region shard)에서 동일한 undefined path 발생 |
— | Confirmed |
| H2 | BIM 모델의 forge_region 필드가 DB에서 null/undefined로 저장됨 |
코드에서 serverModel.forge_region ? ... : Environment.ADF_REGION 패턴으로 fallback 있음 |
fallback이 'US'(DefaultAdfRegion)이므로 undefined인 경우 US로 정상 동작해야 함. 또한 다른 agent(mesh, room)에서는 같은 패턴으로 문제 없음 |
Rejected |
| H3 | Autodesk API 자체의 일시적 장애 (404) | 404 status code | URL 경로 자체가 /undefined/...로 잘못되어 있어 API endpoint에 도달하기 전에 404 반환. 인증은 성공(Bearer token 획득 완료) |
Rejected |
| H4 | forge-apis 라이브러리 버전 간 호환성 문제 (v0.9.10 vs v0.9.12 병존) |
에러 로그에서 forge-apis/0.9.10과 forge-apis/0.9.12 두 버전이 확인됨 |
두 버전 모두 동일하게 /undefined/ URL을 생성하므로 버전 차이가 아닌 근본적인 region 매핑 누락 |
Rejected |
Fix Recommendation#
즉시 조치 (Critical)#
packages/cupix-tesla-thumbnail-agent/src/model/cpbim.ts:59-61—DerivativesApi생성 시 region 값을forge-apis가 지원하는 값("US"또는"EMEA")으로 매핑하는 로직 추가- 또는
cpbim.ts:48에서forgeRegion값이 인식되지 않는 경우(US/EMEA 이외)"US"로 fallback하는 방어 로직 추가 - 실패한 BIM 모델(ID: 2976 등)의 error 상태를 수동으로 복구하여 재처리 가능하도록 조치
단기 개선 (1주 이내)#
@cupix/forge-utils또는 공통 유틸리티에 region 매핑 함수를 추가하여forge-apis가 지원하지 않는 region(APAC/ANZ 등)을 적절한 값으로 변환- 각 agent(thumbnail, mesh, room, forge, bim-revision)에서 동일한 매핑 로직을 사용하도록 통일
- AxiosError에서 잘못된 URL이 감지될 때 구체적인 에러 메시지를 로그에 남기도록
downloadOriginal의 catch 블록 개선
장기 개선 (재발 방지)#
forge-apis라이브러리를 Autodesk Platform Services (APS)의 최신 SDK로 마이그레이션 — 최신 SDK는 APAC region을 공식 지원- SQS 메시지 재시도 시 영구적으로 실패할 요청(잘못된 URL 구성 등)을 조기에 식별하여 불필요한 재시도를 방지하는 circuit breaker 패턴 도입
Monitoring#
- Forge API 호출 URL에
/undefined/패턴이 포함된 경우를 감지하는 알림 추가 - 쿼리 예시:
service:cupixworks-any-thumbnail-agent "developer.api.autodesk.com/undefined"
ApproximateReceiveCount>=MaxReceiveCount도달 빈도 모니터링
Risk Assessment#
- Risk level: medium
- 예상 복잡도: standard — region 매핑 로직 추가 필요, 영향 범위는 ap-southeast-2 region의 thumbnail agent에 한정