ES /docs

ForgeAgents - Error: { code: 303, message: Failed to load fragments for 08f86997-e418-5b88-3419-b489

RCA: ForgeAgents - Failed to load fragments

Overview#

What Happened#

2026-04-23 14:11:33 UTC에 eu-central-1 리전의 cupixworks-any-room-agent 서비스에서 BIM 모델(ID: 1059)의 room extraction 처리 중 Autodesk Forge Model Derivative API의 SVF2 fragment 로딩이 실패했다. @cupix/forge-agents 라이브러리가 fragment ID 08f86997-e418-5b88-3419-b489bcb661bf를 로드하지 못하면서 error code 303을 반환했고, SQS 메시지가 삭제되어 재시도 없이 처리가 종료되었다.

Quick Facts#

Field Value
exception.class ForgeAgents Error (code: 303)
exception.message Failed to load fragments for 08f86997-e418-5b88-3419-b489bcb661bf
top_frame @cupix/forge-agents (private npm package, source unavailable)
env production, eu-central-1

Affected Teams#

Team / Domain Error Count Impact
crcc-sama (team id 78) 1 BIM room extraction 실패 — 해당 BIM 모델의 room 데이터가 추출되지 않음

Timeline#

  1. 14:11:10 UTC — Room extraction 시작, CPBim::fromRoomExtractor 로그: bim level size 14, room size 0
  2. 14:11:13 UTC — 이전 SQS 메시지(4b759fd5) 정상 완료, workspace cleanup 및 메시지 삭제
  3. 14:11:33.730 UTCFailed to use fragments: Failed to load fragments for 08f86997-e418-5b88-3419-b489bcb661bf 에러 발생
  4. 14:11:33.732 UTCForgeAgents - Error: { code: 303, ... } 에러 로그
  5. 14:11:33.734 UTCBaseService::getApiErrorToDeleteMessage — error를 파싱하지 못하고 "undefined error"로 분류
  6. 14:11:33.772 UTC — SQS 메시지(76b2562c) 삭제 (ApproximateReceiveCount: 1, 첫 번째 시도에서 삭제)
  7. 14:11:34.000 UTCBaseService::handlingMessageErrors 최종 에러 로그 출력

Error Log#

Datadog Logs

text
ForgeAgents - Error: { code: 303, message: Failed to load fragments for 08f86997-e418-5b88-3419-b489bcb661bf }

Impact#

  • Service: cupixworks-any-room-agent
  • 발생 횟수: 1
  • 최초 발생: 2026-04-23T14:11:33.732Z
  • 최근 발생: 2026-04-23T14:11:33.732Z

Root Cause Summary#

Autodesk Forge Model Derivative API에서 SVF2 형식 BIM 모델의 fragment 데이터(ID: 08f86997-e418-5b88-3419-b489bcb661bf)를 로드하는 과정에서 실패했다. @cupix/forge-agents 라이브러리의 extract() 함수가 Forge API로부터 fragment 리소스를 가져오지 못하고 error code 303을 반환했다. 이 에러는 Forge API 서버 측에서 해당 fragment가 존재하지 않거나 translation 결과물이 불완전한 경우에 발생하며, cupixworks-any-room-agent 코드에서는 이 에러를 복구할 수 있는 retry 또는 fallback 로직이 없다. 또한 BaseService::getApiErrorToDeleteMessage에서 이 에러 타입을 인식하지 못해 "undefined error"로 분류한 후 SQS 메시지를 삭제하여, 재시도 기회 없이 처리가 종료되었다.

Technical Analysis#

Code Path#

  1. Entry point: RoomService.run() — BIM ID로 room extraction 시작
packages/cupix-tesla-room-agent/src/room-service.ts:58-68typescript
protected run = async (targetId: number): Promise<void> => {
    const cpBim = await this.createCPBimByBimId(targetId);
    if (cpBim) {
        this._modelInProcess = cpBim;
        this._forgeApi.updateRegionFromBim(cpBim.forgeRegion);
        if (cpBim.workspaceDirPath) this.setModelWorkspace(cpBim.workspaceDirPath);

        if (cpBim.isGenerateMasterViews) {
            await this.forgeAuth.authenticate();
            await this.updateBimRoomState(targetId, TESLA.UpdateBimRequest.RoomStateEnum.Extracting);
            await this.runRoomExtractor(cpBim);
  1. Room extraction 호출: RoomExtractManager.execute() → child process 실행
packages/cupix-tesla-room-agent/src/manager/room-extract.manager.ts:25-42typescript
async execute(params: RoomExtractorParams): Promise<RoomExtractorResults> {
    logger.debug('RoomExtractManager::execute | begin with urn:', params.urn);
    try {
        const result = await this.childProcessManager.execute<RoomExtractorResults>('execute', params);
        logger.debug('RoomExtractManager::execute | completed successfully');
        return result;
    } catch (error) {
        logger.error('RoomExtractManager::execute | error:', error);
        const errorCode = ErrorCode.Agent.RoomExtractorExecute;
        if (this.setJobErrorCode) {
            this.setJobErrorCode(errorCode);
        }
        throw error;
    }
}
  1. Child process에서 ForgeAgent.extract() 호출: SVF2 format의 경우 @cupix/forge-agents를 사용
packages/cupix-tesla-room-agent/src/process/room-extractor.process.ts:39-53typescript
if (params.formatType === 'svf2') {
    const result = await ForgeAgent.extract(params.apiConfig, params.urn, {
        extractRoom: true,
        extractMeta: true,
        region: params.region
    });

    if (result.Error == undefined) {
        extract = result;
    } else if (result.Error === ForgeAgentErrorCode.FORGE_SOURCE_INVALID_MANIFEST) {
        this.log('RoomExtractorProcess::execute - svf2 manifest is invalid, try svf1 process');
        extract = await RoomExtractor.room_extract(params.token, params.urn);
    } else {
        throw new Error('Failed to get rooms from svf2');
    }
  1. Failure point: @cupix/forge-agents 라이브러리 내부 (private npm 패키지 — 소스 직접 확인 불가)

    • ForgeAgent.extract() 내부에서 Autodesk Forge Model Derivative API를 호출하여 SVF2 manifest를 파싱하고, 각 fragment를 로드한다.
    • Fragment ID 08f86997-e418-5b88-3419-b489bcb661bf 로드 실패 시 error code 303과 함께 에러를 throw한다.
    • 에러 메시지 패턴: "Failed to use fragments: Failed to load fragments for {fragment_id}""ForgeAgents - Error: { code: 303, ... }"
  2. Error handling: BaseService::handlingMessageErrors에서 에러를 잡지만, 에러 객체가 HTTP response가 아닌 JS Error 객체이므로 getApiErrorToDeleteMessage에서 "undefined error"로 분류

packages/base/src/base-service.ts:240-276typescript
private getApiErrorToDeleteMessage = (error: any): any => {
    if (error == undefined) {
        logger.warn('BaseService::getApiErrorToDeleteMessage | undefined error');
        return 'undefined error';
    }
    // ... error.errno/code/syscall 체크 — JS Error에는 없으므로 통과
    const response = CPUtils.isJsonString(error) ? JSON.parse(error) : error.response;
    if (response == undefined) {
        logger.warn('BaseService::getApiErrorToDeleteMessage | undefined response', error);
        return 'undefined response';
    }
    // ... HTTP statusCode 기반 분류 — 해당사항 없음

ForgeAgent.extract()가 던지는 에러는 { code: 303, message: "..." } 형태이지만, error.response가 없는 JS Error 객체이므로 response == undefined 분기를 타게 된다. 이 경우 'undefined response'를 반환하여 apiErrorObject가 truthy → SQS 메시지 삭제가 실행된다.

Log Evidence#

Datadog 쿼리로 에러 발생 전후 3분간의 모든 로그를 검색했다:

text
service:cupixworks-any-room-agent
from: 2026-04-23T14:10:00Z to: 2026-04-23T14:13:00Z

실행 흐름 전체를 보여주는 10개 로그가 확인되었다:

text
14:11:10.718Z [info]  CPBim::fromRoomExtractor | bim level size: 14, room size: 0
14:11:13.126Z [info]  BaseService::cleanUpAnythingRelatedModel | path: /tmp/workspace/944
14:11:13.127Z [info]  AwsQueueManager::deleteMessage | begin - queue url: https://sqs.eu-central-1.amazonaws.com/002596530511/cupix-tesla-room-agent-production
14:11:13.161Z [info]  AwsQueueManager::deleteMessage | end - message id: 4b759fd5-d835-40b2-9f66-ca428a95f079
14:11:33.730Z [error] Failed to use fragments: Failed to load fragments for 08f86997-e418-5b88-3419-b489bcb661bf
14:11:33.732Z [error] ForgeAgents - Error: { code: 303, message: Failed to load fragments for 08f86997-e418-5b88-3419-b489bcb661bf }
14:11:33.734Z [warn]  BaseService::getApiErrorToDeleteMessage | undefined error
14:11:33.734Z [info]  AwsQueueManager::deleteMessage | begin - queue url: ...cupix-tesla-room-agent-production
14:11:33.772Z [info]  AwsQueueManager::deleteMessage | end - message id: 76b2562c-6f9c-459b-9b64-eb8cb95d76bf
14:11:34.000Z [error] BaseService::handlingMessageErrors | Error and message object - {"error":"undefined error","sqsMessage":{"MessageId":"76b2562c-...","Attributes":{"ApproximateReceiveCount":"1"}}}

주목할 점:

  • 14:11:10에 이전 BIM의 room extraction 결과가 level 14개, room 0개로 완료됨
  • 이전 메시지(4b759fd5)가 정상 삭제된 직후 새 메시지(76b2562c)의 처리가 시작됨
  • Fragment 로딩 실패 후 20초 만에 에러 발생 (14:11:13 → 14:11:33)
  • ApproximateReceiveCount: 1 — 첫 번째 수신에서 바로 삭제됨 (재시도 기회 없음)

2일간 ForgeAgents 에러 패턴 검색:

text
service:cupixworks-any-room-agent ("ForgeAgents" OR "code: 303")
from: 2026-04-22T00:00:00Z to: 2026-04-23T23:59:59Z

9건의 ForgeAgents 에러가 확인되었으며, 대부분은 code 305 (geometry 로딩 실패)이고 code 303 (fragment 로딩 실패)은 이 1건뿐이다:

text
Apr 23 14:11:33Z | code: 303 | Failed to load fragments for 08f86997...  (eu-central-1)
Apr 23 13:34:49Z | code: 305 | Failed to load geometries for 2e3c1b6a... (us-west-2)
Apr 23 02:36:54Z | code: 305 | Failed to load geometries for 59e15fc1...
Apr 23 01:07:14Z | code: 305 | Failed to load geometries for 59e15fc1...
Apr 22 15:46:24Z | code: 305 | Failed to load geometries for 648caece...
Apr 22 12:26:17Z | code: 1   | Failed to get properties and children
Apr 22 05:13:07Z | code: 305 | Failed to load geometries for 9814b08e...
Apr 22 05:11:23Z | code: 305 | Failed to load geometries for 99d37c96...
Apr 22 05:04:29Z | code: 305 | Failed to load geometries for 34d561e8...

Cross-service 검색에서 다른 서비스(cupixworks-api, cupixworks-worker 등)에서 이 fragment UUID와 관련된 에러는 발견되지 않았다.

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 Autodesk Forge API에서 SVF2 translation 결과물이 불완전하여 특정 fragment가 존재하지 않거나 접근 불가 에러 코드 303이 fragment 로딩 실패를 의미함. 2일간 유사 패턴(code 305 geometry 실패)이 다수 발생하여 Forge API 측 리소스 가용성 문제가 반복적임을 확인. Fragment UUID 08f86997...에 대한 info/warn 로그가 전혀 없어 API 호출 단계에서 즉시 실패한 것으로 보임 Confirmed
H2 Forge API 인증 토큰 만료 또는 권한 문제 에러 직전 동일 호스트에서 이전 메시지가 정상 처리 완료됨 (14:11:13). 에러 코드가 인증 관련(401/403)이 아닌 303(fragment 로딩 실패)이며, forgeAuth.authenticate()는 각 메시지 처리 시 호출됨 Rejected
H3 네트워크 일시적 장애 (eu-central-1 → Forge API) Forge API 서버가 미국에 있고 eu-central-1에서의 지연이 있을 수 있음 에러 메시지가 timeout이 아닌 명확한 "Failed to load fragments" 코드 303이며, 동시간대 다른 에러 로그에 네트워크 에러(ECONNREFUSED, ETIMEDOUT 등)가 없음 Rejected
H4 BIM 모델 자체의 문제 (손상된 모델이 불완전한 translation 결과 생성) room extraction에서 "room size: 0"으로 이미 비정상적 결과. crcc-sama 팀의 특정 BIM 모델(ID 1059)에서만 발생 다른 팀/모델에서도 유사 에러(code 305)가 발생하므로 특정 모델만의 문제는 아님 Inconclusive

Fix Recommendation#

즉시 조치 (Critical)#

  • 현재 에러는 Autodesk Forge API 측의 리소스 가용성 문제로, 에이전트 코드만으로는 근본 해결이 어렵다.
  • room-extractor.process.ts:46-53에서 result.Error가 303 (fragment 로딩 실패) 또는 305 (geometry 로딩 실패)인 경우, 바로 throw하지 않고 SVF1 fallback (RoomExtractor.room_extract)을 시도하도록 수정. 현재는 FORGE_SOURCE_INVALID_MANIFEST일 때만 SVF1 fallback이 동작한다.

단기 개선 (1주 이내)#

  • BaseService::getApiErrorToDeleteMessage (base-service.ts:240-276)에서 @cupix/forge-agents가 던지는 에러 형태({ code, message })를 인식하도록 개선. 현재는 HTTP response 형태의 에러만 파싱하므로, ForgeAgentErrorCode 기반 에러를 "undefined response"로 분류하고 첫 번째 시도에서 SQS 메시지를 삭제해 버린다.
  • Fragment/geometry 로딩 실패 시 SQS 메시지를 즉시 삭제하지 않고 재시도할 수 있도록 MaxReceiveCount 분기를 활용. Forge API의 일시적 오류일 경우 재시도로 성공할 가능성이 있다.

장기 개선 (재발 방지)#

  • @cupix/forge-agents 라이브러리 내부에 retry 로직 추가 — fragment/geometry 로딩 실패 시 exponential backoff으로 2-3회 재시도 후 실패 처리.
  • Forge translation 상태를 사전 검증: room extraction 시작 전에 Forge manifest의 derivative status가 complete인지 확인하고, 개별 resource의 가용성을 검증하는 pre-check 단계를 추가.
  • ForgeAgents 에러 코드별 severity 분류: code 303/305는 외부 API 의존성 문제이므로 error 대신 warn 레벨 로깅을 검토할 수 있다 (발생 빈도에 따라 판단).

Monitoring#

  • ForgeAgents 에러 코드별 발생 추이 모니터링:
text
service:cupixworks-any-room-agent "ForgeAgents - Error"
  • Fragment/geometry 로딩 실패율 알림 (1시간 내 5건 이상 시 alert):
text
service:cupixworks-any-room-agent ("code: 303" OR "code: 305")
  • Room extraction 결과에서 room size 0인 비율 추적:
text
service:cupixworks-any-room-agent "room size: 0"

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: standard
  • 근거: 발생 빈도가 낮고 (code 303은 2일간 1건), 단일 BIM 모델의 room extraction 실패로 영향 범위가 제한적이다. 다만 code 305 포함 시 2일간 9건의 ForgeAgents 에러가 발생하고 있어, SVF1 fallback 적용으로 상당수 해결 가능할 것으로 보인다.