ES /docs

ForgeService::handlingMessageErrors | Error and message object - {"error":{"statusCode":403,"request

RCA: ForgeService::handlingMessageErrors | 403 Bim not found (ENT4000)

Overview#

What Happened#

2026-04-30 20:48:39 UTC에 cupixworks-any-forge-agent 서비스에서 BIM 업로드 처리 중 내부 API로부터 HTTP 403 응답(ENT4000: "Bim not found")을 수신했다. BIM ID 19351이 삭제(trash)된 상태에서 SQS 메시지가 처리되면서 발생한 단건 에러다.

Quick Facts#

Field Value
exception.class ForgeService::handlingMessageErrors
exception.message statusCode:403, ENT4000, Bim not found
top_frame forge-service.ts:412
env production, us-west-2

Timeline#

  1. 20:48:39.459Z — SQS 메시지 수신, runByMessage 시작 (bim_id: 19351, bim_revision_id: 23188)
  2. 20:48:39.521Z — 세션 인증 완료 (session_id: f4640817...)
  3. 20:48:39.551Z — API 호출 실패: HTTP 403, ENT4000 "Bim not found"
  4. 20:48:39.553Z — SQS 메시지 삭제 시작 (terminal failure로 판단)
  5. 20:48:39.584ZhandlingMessageErrors에서 error 레벨 로그 기록

Error Log#

Datadog Logs

text
ForgeService::handlingMessageErrors | Error and message object - {"error":{"statusCode":403,"requestUriHref":"http://api-tesla.cupix.internal/api/v1/bims/19351?fields%5B0%5D=id&fields%5B1%5D=name&fields%5B2%5D=state&fields%5B3%5D=resource_state&fields%5B4%5D=forge_state&fields%5B5%5D=room_state&fields%5B6%5D=encoded_forge_urn&fields%5B7%5D=forge_workflow_id&fields%5B8%5D=last_bim_revision&fields%5B9%5D=bim_source&fields%5B10%5D=meta&fields%5B11%5D=created_at&fields%5B12%5D=thumbnail_urls","bodyResult":{"code":"ENT4000","type":"Cupix::Errors::NotFound","reason":"Bim not found","message":"Bim not found"},"modelId":23188},"sqsMessage":{"MessageId":"29eb13e5-159c-4c71-b075-7ffd8f13b1e7","Attributes":{"ApproximateReceiveCount":"1"}}}

Impact#

  • Service: cupixworks-any-forge-agent
  • 발생 횟수: 1
  • 최초 발생: 2026-04-30T20:48:39.584Z
  • 최근 발생: 2026-04-30T20:48:39.584Z
  • 사용자 영향: BIM 19351의 Forge 변환이 실패했으나, 해당 BIM은 이미 삭제된 상태이므로 실질적 사용자 영향은 없음

Root Cause Summary#

BIM 19351이 SQS 메시지 enqueue 이후 삭제(trash)되었다. Forge agent가 메시지를 처리하며 내부 API를 호출했을 때, Tesla API의 base_repository.rb는 해당 BIM이 trash 상태임을 감지하고 ENT4000 코드와 함께 Cupix::Errors::NotFound를 raise했다. 이 예외는 client_error_controller.rb에서 HTTP 403으로 매핑된다. Forge agent의 createCPBimByBimId 메서드는 ARG10002 코드만 graceful하게 처리(resolve undefined)하며, ENT4000은 reject되어 handlingMessageErrors에서 error 레벨로 로깅된다.

Technical Analysis#

Code Path#

  1. Entry point — SQS 메시지 수신 후 checkingQueue에서 runByMessages 호출:
forge-service.ts:90-93typescript
try {
    await this.runByMessages();
} catch (error) {
    await this.handlingMessageErrors(error);
}
  1. Message processingrunByMessage가 bim_id를 추출하고 uploadBim 호출:
forge-service.ts:199-201typescript
private uploadBim = async (bimId: number, bimRevisionId: number, forgeOutputFormatType: string): Promise<void> => {
    logger.debug('ForgeService::uploadBim | begin');
    const cpBim = await this.createCPBimByBimId(bimId);
  1. API call & error handlingcreateCPBimByBimId에서 BIM 조회 시 ARG10002만 graceful 처리:
forge-service.ts:295-313typescript
private createCPBimByBimId = (bimId: number): Promise<CPBim | undefined> => new Promise((resolve, reject) => {
    this.cupixApi.bim.get(bimId)
        .then(resPano => {
            resolve(new CPBim(resPano));
        })
        .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('ForgeService::createCPBimByBimId | end - reason: %s', reason);
                if (code === 'ARG10002') return resolve(undefined);
            }
            reject(ec);
        });
});
  1. Tesla API sidebase_repository.rb에서 trash된 BIM은 ENT4000으로 raise:
app/repositories/base_repository.rb:347-352ruby
if model.nil?
  if self.where(attrs).in_trash.present?
    raise Cupix::Errors::NotFound.new(code: 'ENT4000', reason: "#{current_class.name} not found")
  else
    raise Cupix::Errors::NotFound.new(code: 'ARG10002', reason: "#{current_class.name} not found")
  end
end
  1. HTTP 403 매핑NotFound 예외가 403으로 응답:
app/controllers/concerns/client_error_controller.rb:27,55-56ruby
rescue_from Cupix::Errors::NotFound, with: :not_found_403_error

def not_found_403_error(exception)
  raise_error(403, exception)
end
  1. Error logging — reject된 에러가 handlingMessageErrors에 도달, error 레벨 로그 기록:
forge-service.ts:390-414typescript
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);
            } catch (error) {
                logger.error('ForgeService::handlingMessageErrors | Errors in error handling - %s', JSON.stringify(error));
            }
        }
    }
    await this.cleanUpAnythingRelatedModel();
    logger.error('ForgeService::handlingMessageErrors | Error and message object - %s', JSON.stringify(errorAndMessage));
};

Log Evidence#

Datadog 검색 쿼리:

text
service:cupixworks-any-forge-agent status:error @environment:production "ForgeService::handlingMessageErrors"
text
service:cupixworks-any-forge-agent @environment:production 19351

전체 이벤트 시퀀스 (125ms 이내):

text
20:48:39.459 [info]  ForgeService::runByMessage | bim_id: 19351  bim_revision_id: 23188
20:48:39.521 [info]  CupixAuth::setSession | session_id: f4640817c06d4480b9d51436faf669582cfc897b
20:48:39.551 [warn]  CupixAuth::handleError | Response statusCode: 403, requestUriHref: .../bims/19351... body: ENT4000 / Cupix::Errors::NotFound / Bim not found
20:48:39.552 [warn]  ForgeService::createCPBimByBimId | end - reason: Bim not found
20:48:39.552 [warn]  ForgeService::getApiErrorToDeleteMessage | error msg - statusCode 403, Bim not found, modelId: 23188
20:48:39.553 [info]  AwsQueueManager::deleteMessage | begin - queue url: ...cupix-tesla-forge-agent-production
20:48:39.583 [info]  AwsQueueManager::deleteMessage | end - message id: 29eb13e5-159c-4c71-b075-7ffd8f13b1e7
20:48:39.584 [warn]  ForgeService::cleanUpAnythingRelatedModel | end - undefined modelDirPath
20:48:39.584 [error] ForgeService::handlingMessageErrors | Error and message object - {...}

핵심 관찰:

  • SQS 메시지가 정상적으로 삭제됨 (재처리 없음)
  • ApproximateReceiveCount: 1 — 첫 번째 시도에서 바로 실패
  • 1.5시간 검색 범위 내 이 서비스에서 다른 403 에러 없음 (단건 이벤트)
  • 팀: gmoal (id: 1202), 사용자: eloisareyes@salmx.com (id: 46746)

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 BIM이 SQS enqueue 후 삭제(trash)되어 API가 ENT4000 반환 API 응답 ENT4000 = "Record has trashed" (entity.yml:49), base_repository.rb:348-349에서 in_trash.present? 조건 확인 시 ENT4000 raise Confirmed
H2 세션 권한 부족으로 403 발생 HTTP 403 응답 에러 코드가 PERM10000이 아닌 ENT4000, 세션 인증은 정상 완료 (20:48:39.521Z) Rejected
H3 Forge agent의 에러 코드 분기에서 ENT4000 미처리 forge-service.ts:309에서 ARG10002만 체크, ENT4000은 reject됨 이는 의도적 설계일 수 있음 (trash된 BIM은 다른 처리가 필요할 수 있음) Confirmed (contributing factor)

Fix Recommendation#

즉시 조치 (Critical)#

  • 파일: applications/agents/packages/cupix-tesla-forge-agent/src/forge-service.ts:309
  • createCPBimByBimId의 catch 블록에서 ENT4000 코드도 ARG10002와 동일하게 resolve(undefined)로 처리하도록 변경. 삭제된 BIM에 대한 Forge 처리는 불필요하므로 graceful skip이 적절함.
  • 이렇게 하면 SQS 메시지가 정상 삭제되면서 error 레벨 로그 대신 warn 레벨에서 종료됨.

단기 개선 (1주 이내)#

  • handlingMessageErrors의 로그 레벨을 재검토. 현재 모든 API 에러를 error 레벨로 로깅하지만, "Bim not found"처럼 예상 가능한 운영 시나리오는 warn으로 충분함.
  • 삭제된 리소스에 대한 SQS 메시지는 agent가 graceful하게 처리하는 것이 맞으므로, 관련 에러 코드(ENT4000, ENT5000 등)를 허용 목록에 추가.

장기 개선 (재발 방지)#

  • BIM 삭제 시 관련 SQS 메시지를 취소하거나, enqueue 전에 BIM 상태를 확인하는 로직을 Tesla API 쪽에 추가.
  • Tesla API에서 NotFound를 HTTP 404로 매핑하는 것을 검토 (현재 403으로 매핑하여 혼란 유발).

Monitoring#

추가 권장 메트릭:

text
service:cupixworks-any-forge-agent "ForgeService::handlingMessageErrors" "ENT4000"
text
service:cupixworks-any-forge-agent status:error @environment:production | 일일 count 추이
  • ENT4000 에러가 급증하면 BIM 대량 삭제 이벤트를 의심할 수 있음
  • 현재 단건 발생이므로 즉각적인 알림 설정은 불필요하나, 패턴 모니터링 권장

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: trivial
  • 사용자 영향: 없음 (이미 삭제된 BIM, agent가 메시지를 정상 삭제하여 재처리 안 됨)
  • 수정 범위: forge-service.ts 1줄 조건 추가