ES /docs

HTTP request failed

RCA: HTTP request failed

Error Log#

Datadog Logs

text
HTTP request failed

Impact#

  • Service: cupixworks-any-room-agent
  • Team: pace
  • 발생 횟수: 3
  • 최초 발생: 2026-04-08T06:26:46.452Z
  • 최근 발생: 2026-04-08T06:30:22.375Z

Root Cause Summary#

BIM 3274와 BIM 3273이 room-agent 처리 도중에 삭제(또는 접근 불가 상태로 전환)되어 Tesla API가 403 ENT4000 ("Bim not found") 응답을 반환했습니다. room-agent는 RoomService::run() 내에서 room extraction 완료 후 updateBimRoomState() 호출 시 PUT /api/v1/bims/3274 요청이 실패하며 HttpError가 발생했습니다. API 로그에 따르면 06:24~06:25 시점에는 동일 BIM에 대해 200 응답이 정상 반환되었으나, 06:26:47부터 모든 요청이 403으로 전환되었습니다. createCPBimByBimId catch 블록은 ARG10002 에러 코드만 graceful하게 처리하며 ENT4000은 처리하지 않아 예외가 상위로 전파됩니다. 동일 세션에서 cupixworks-any-mesh-agent도 같은 BIM에 대해 동일한 에러를 경험했습니다.

Technical Analysis#

Code Path#

  • Entry point: cupix-tesla-room-agent/src/app.ts:39RoomService().init() 호출
  • SQS 메시지 수신 후 BaseService::runByMessage() (base-service.ts:153)에서 메시지 처리 시작
  • RoomService::run() (room-service.ts:58) 실행 — createCPBimByBimId(targetId) 호출로 BIM 데이터 로드
  • createCPBimByBimId (room-service.ts:102-120)에서 cupixApi.bim.get(bimId) 호출 — 이 시점에서는 BIM이 존재하여 정상 반환
  • room extraction 완료 후 importRoomWorkareasFromBim() (room-service.ts:465) 및 importRoomsFromBim() (room-service.ts:370) 호출
  • importRoomsFromBim 내에서 cupixApi.room.getAll(cpBim.id) (room-service.ts:381)로 GET /api/v1/rooms?bim_id=3274 호출 시 403 발생
  • Failure point: updateBimRoomState() (room-service.ts:158-165) — cupixApi.bim.update(bimId, ...) 호출 시 PUT /api/v1/bims/3274 요청이 403 반환
typescript
// room-service.ts:158-165
private updateBimRoomState = async (bimId: number, state: TESLA.UpdateBimRequest.RoomStateEnum): Promise<void> => {
    logger.debug('RoomService::updateBimRoomState | begin');
    logger.debug('RoomService::updateBimRoomState | state: %s', state);
    await this.cupixApi.bim.update(bimId, {  // PUT /api/v1/bims/{bimId} → 403 "Bim not found"
        room_state: state
    });
    logger.debug('RoomService::updateBimRoomState | end');
};

bim.update() 내부에서 @tesla/typescript-node-sdkBimApi.updateBim() (bimApi.js:3351)이 HTTP 403 응답을 받아 HttpError: HTTP request failed를 throw합니다.

typescript
// bim.api.ts:47-51
async update(bimId: number, updateBimRequest: TESLA.UpdateBimRequest): Promise<TESLA.Bim> {
    const api = await this.api();
    const res = await api.updateBim(bimId, Fields.BimFields, updateBimRequest);  // HttpError 발생 지점
    return unwrapAttributes(res);
}

에러는 BaseService::checkingQueue() (base-service.ts:107-111)의 catch 블록으로 전파되어 handlingMessageErrors()에서 처리됩니다:

typescript
// base-service.ts:290-313
private handlingMessageErrors = async (error: any): Promise<void> => {
    // ...
    const apiErrorObject = this.getApiErrorToDeleteMessage(error);
    if (apiErrorObject != undefined || this.checkReceiveCountToDeleteMessage()) {
        // 403은 400-500 범위에 해당하므로 SQS 메시지 삭제 후 error state 업데이트 시도
        await this.deleteByMessage(this.messageInProcess);
        if (this._modelInProcess != undefined && this._modelInProcess.id > 0)
            await this.updateErrorState(this._modelInProcess);  // BIM이 삭제된 상태에서 다시 API 호출
    }
    logger.error('BaseService::handlingMessageErrors | Error and message object - %s', ...);
};

createCPBimByBimId의 catch 블록은 ARG10002 코드만 graceful하게 처리하며, ENT4000 코드는 reject(ec)로 전파됩니다:

typescript
// room-service.ts:110-119
.catch(ec => {
    const body = ec?.response?.body;
    if (body) {
        const code = body.result?.code;
        const reason = body.result?.reason ? body.result.reason : body.result?.message;
        logger.warn('RoomService::createCPBimByBimId | end - reason: %s', reason);
        if (code === 'ARG10002') return resolve(undefined);  // ARG10002만 처리, ENT4000은 미처리
    }
    reject(ec);
});

Log Evidence#

사용한 Datadog 쿼리:

text
service:cupixworks-any-room-agent status:error @environment:production "HTTP request failed"
text
service:cupixworks-any-room-agent @environment:production @session_id:aef9cd76d804ac5b3e1420c69736848f9edef3b8
text
service:cupixworks-api @environment:production @http.url_details.path:/api/v1/bims/3274

에러 로그 (Log ID 1 — 06:26:46.452Z):

json
{
  "message": "HTTP request failed",
  "error": {
    "kind": "HttpError",
    "stack": "bimApi.js:3351:40 in @tesla/typescript-node-sdk"
  },
  "http": {
    "status_code": 403,
    "method": "PUT",
    "url": "http://api-tesla.cupix.internal/api/v1/bims/3274"
  },
  "response_body": "{\"result\":{\"reason\":\"Bim not found\",\"code\":\"ENT4000\",\"type\":\"Cupix::Errors::NotFound\",\"message\":\"Bim not found\"}}"
}

API 응답 타임라인 (BIM 3274):

시각 (UTC) Method Endpoint Status 비고
06:24:01.952 GET /api/v1/bims/3274 200 정상
06:24:02.989 PUT /api/v1/bims/3274 200 정상
06:25:06.015 PUT /api/v1/bims/3274 200 마지막 정상 응답
06:26:47.141 PUT /api/v1/bims/3274 403 "Bim not found" 시작
06:30:23.276 PUT /api/v1/bims/3274 403 mesh-agent도 동일 실패

Room agent 실행 흐름 (06:26:44~06:26:47):

text
06:26:44.594 [info]  CPBim::fromRoomExtractor | bim level size: 29, room size: 668
06:26:44.607 [info]  RoomService::importRoomWorkareasFromBim | bim room size: 668
06:26:46.361 [info]  RoomService::importRoomsFromBim | bim room size: 668
06:26:46.393 [warn]  BaseService::getApiErrorToDeleteMessage | 403 on GET /api/v1/rooms?...bim_id=3274 — "Bim not found"
06:26:46.395 [info]  AwsQueueManager::deleteMessage | begin
06:26:46.425 [info]  AwsQueueManager::deleteMessage | end (msg: 995639c5-...)
06:26:46.452 [error] "HTTP request failed" — HttpError, 403, PUT /api/v1/bims/3274
06:26:46.453 [error] BaseService::handlingMessageErrors | error + SQS message dump

영향받은 엔티티:

  • BIM ID: 3273, 3274
  • User: Bryan Seng (id: 7606, bryan@pacebuildinggroup.com.au)
  • Team: pace (id: 173)
  • Region: ap-southeast-2
  • Session: aef9cd76d804ac5b3e1420c69736848f9edef3b8

Fix Recommendation#

즉시 조치 (Critical)#

  • room-service.ts:110-119createCPBimByBimId의 catch 블록에서 ENT4000 ("Bim not found") 에러 코드도 ARG10002와 동일하게 resolve(undefined)로 처리하여 graceful exit 하도록 수정. BIM이 삭제된 상태에서는 추가 처리를 시도하지 않고 메시지를 정상 완료 처리해야 합니다.
  • 동일한 패턴이 cupixworks-any-mesh-agent에도 존재하는지 확인 필요 — MeshService::createCPBimByBimId에도 같은 수정 적용.

단기 개선 (1주 이내)#

  • BaseService::handlingMessageErrors() (base-service.ts:305)에서 updateErrorState() 호출 시, BIM이 이미 삭제되었을 수 있으므로 해당 호출을 try-catch로 감싸거나, "not found" 에러는 무시하도록 로직 추가. 현재는 에러 핸들링 중에 다시 동일한 API 에러가 발생할 수 있습니다.
  • run() 메서드의 장시간 실행 흐름 중간에 BIM 존재 여부를 재확인하는 guard 체크 추가 고려. room extraction이 수 분 소요되는 동안 BIM이 삭제될 수 있는 race condition 존재.

장기 개선 (재발 방지)#

  • Agent 아키텍처에서 "entity not found" 에러를 일관되게 처리하는 공통 패턴 도입. 현재 각 agent의 createCPBimByBimId가 개별적으로 에러 코드를 체크하며, 새로운 에러 코드(ENT4000)가 추가될 때 누락될 수 있습니다.
  • Tesla API에서 BIM 삭제 시 해당 BIM을 참조하는 SQS 메시지를 무효화하는 메커니즘 검토. 현재는 BIM 삭제와 agent 처리 사이에 race condition이 구조적으로 존재합니다.

Monitoring#

  • BIM not found 에러 빈도 모니터링:
text
service:cupixworks-any-room-agent status:error "Bim not found" @environment:production
  • 삭제된 BIM에 대한 agent 처리 시도 추적:
text
service:(cupixworks-any-room-agent OR cupixworks-any-mesh-agent) "getApiErrorToDeleteMessage" "ENT4000" @environment:production

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: trivial