ES /docs

HTTP request failed

RCA: HTTP request failed (mesh agent — trashed BIM 조회 실패)

Overview#

What Happened#

2026-07-15 15:17 KST, cupixworks-any-mesh-agent(tesla mesh agent, ap-southeast-1 / gammon-forida) 가 BIM 227 을 SQS 로 수신한 뒤 tesla API 로 조회하는 첫 단계에서 HttpError: HTTP request failed (statusCode 403, body ENT4000 Cupix::Errors::NotFound "Bim not found") 을 만나 mesh 추출 파이프라인이 실패로 처리됐다. 동일 패턴(다른 BIM ID) 이 24 시간 내 최소 3 건(1712, 1714, 229, 227) 관측되어 재발성 이슈다.

Quick Facts#

Field Value
exception.class HttpError
exception.message HTTP request failed
top_frame @tesla/typescript-node-sdk/api/bimApi.js:1191
runtime Node.js (tesla mesh agent, pnpm bundle /tmp/agent/dist)
downstream http://api-tesla.cupix.internal/api/v1/bims/{id}403 ENT4000
env production, region ap-southeast-1

Affected Teams#

Team / Domain Error Count Impact
gammon-forida (tenant cupix, ap-southeast-1) 1 (해당 클러스터) BIM 227 mesh 추출 실패 → mesh_state=error 로 표시되어 downstream 서비스(3D viewer, siteinsights) 에서 mesh 를 사용할 수 없음
24h 전체 mesh-agent (같은 fingerprint 계열) 4+ 건 (bim 227, 229, 1712, 1714) trashed BIM 이 SQS 에 남아 있으면 매번 error 로그 발생, SQS 메시지는 삭제 처리됨

Timeline#

  1. 2026-07-14 05:34 ~ 13:44 KST — 전날 svc:cupixworks-any-mesh-agent::unknown 인시던트(5 clusters, resolved) 발생. 상태 보드에 recent 로 기록됨.
  2. 2026-07-15 15:16:15 KST — BIM 229 처리 중 createCPBimByBimId | end - reason: Bim not found (warn) — 다른 코드 경로(ARG10002) 가 정상 흡수한 케이스.
  3. 2026-07-15 15:17:24 KST — BIM 227 처리 중 tesla API 가 403 ENT4000 (trashed) 응답. mesh-service 는 ENT4000 을 처리하지 않아 error 로 propagate. MeshService::run | error: HTTP request failed 로그 발생 (본 클러스터의 대표 로그).
  4. 2026-07-15 15:17:24 KSTBaseService::handlingMessageErrors 가 statusCode 403 을 400 대역 규칙으로 판정하고 SQS 메시지를 삭제. workspace /tmp/workspace/227 정리.

Error Log#

Datadog Logs

text
HTTP request failed

Datadog에서 확인한 stack 및 응답:

json
{
  "stack": "HttpError: HTTP request failed\n    at Request._callback (/tmp/agent/dist/node_modules/.pnpm/@tesla+typescript-node-sdk@1.13.3-SNAPSHOT.202605301249_1e9855b03300e7077469e8a23e5d7e36/node_modules/@tesla/typescript-node-sdk/api/bimApi.js:1191:40) ...",
  "message": "HTTP request failed",
  "response": { "body": {}, "statusCode": 403 },
  "statusCode": 403,
  "name": "HttpError"
}

동일 시점 handlingMessageErrors 페어링 로그(원문):

json
{
  "error": {
    "statusCode": 403,
    "requestUriHref": "http://api-tesla.cupix.internal/api/v1/bims/227?fields[0]=id&...",
    "bodyResult": {
      "code": "ENT4000",
      "type": "Cupix::Errors::NotFound",
      "reason": "Bim not found",
      "message": "Bim not found"
    },
    "modelId": 227
  },
  "sqsMessage": { "MessageId": "912c9efa-6a43-4026-b5f4-4b6e5e282a75", "Attributes": { "ApproximateReceiveCount": "1" } }
}

Impact#

  • Service: cupixworks-any-mesh-agent
  • Team: gammon-forida
  • 발생 횟수: 1 (본 클러스터). 24h 내 동일 fingerprint 계열 4+ 건.
  • 최초 발생: 2026-07-15 15:17 KST
  • 최근 발생: 2026-07-15 15:17 KST

BIM 이 이미 trash 로 이동된 상태이므로 사용자 체감 영향은 제한적이지만, 매 발생마다 mesh_state=error 를 (이미 삭제된) BIM 에 기록하려는 시도가 뒤따르고 error 레벨 로그가 alerting 노이즈로 남는다.

Root Cause Summary#

Mesh agent 의 MeshService.createCPBimByBimId 는 tesla API 가 반환하는 "not found" 응답 중 code === 'ARG10002' 만 성공적으로 흡수해 resolve(undefined) 로 조용히 종료한다. 그러나 tesla BaseRepository#show 는 대상 레코드가 trash 상태일 때 ENT4000 을, 완전 부재일 때 ARG10002 를 반환한다 (app/repositories/base_repository.rb:351-356). SQS 메시지 enqueue 이후 BIM 이 소프트 삭제되면 tesla 가 403 ENT4000 을 돌려주지만, mesh agent 는 이를 whitelist 하지 않아 HttpError 로 그대로 throw → MeshService::run 의 catch 블록이 HTTP request failed 로 error 로깅. 이후 getApiErrorToDeleteMessage 가 4xx 를 SQS 에서 제거해 재시도되지 않지만, 매번 error 레벨 스택트레이스가 남는다.

Technical Analysis#

Code Path#

  • Entry point: applications/agents/packages/cupix-tesla-mesh-agent/src/mesh-service.ts:101 (MeshService.run)
  • 첫 API 호출: MeshService.createCPBimByBimIdthis.cupixApi.bim.get(bimId) (line 134). tesla GET /api/v1/bims/{id} 로 매핑.
  • Failure point: mesh-service.ts:145ENT4000 이 whitelist 에 없어 reject(ec) 실행
  • Propagation: run 의 try/catch (line 117-120) 가 HTTP request failed 로 error 로그 남기고 updateErrorState 호출
applications/agents/packages/cupix-tesla-mesh-agent/src/mesh-service.ts:131-149typescript
private createCPBimByBimId = (bimId: number): Promise<CPBim | undefined> => new Promise((resolve, reject) => {
	logger.debug('MeshService::createCPBimByBimId | begin');
	logger.debug('MeshService::createCPBimByBimId | bimId: %d', bimId);
	this.cupixApi.bim.get(bimId)
		.then(resBim => {
			logger.debug('MeshService::createCPBimByBimId | end');
			resolve(new CPBim(resBim));
		})
		.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('MeshService::createCPBimByBimId | end - reason: %s', reason);
				if (code === 'ARG10002') return resolve(undefined);   // ENT4000 은 처리 안 됨
			}
			reject(ec);
		});
});

Tesla 측(downstream) 이 두 코드를 구분하는 지점:

app/repositories/base_repository.rb:351-356ruby
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

기대 동작: BIM 이 trash 상태여도 mesh agent 는 warn 로그 후 조용히 skip (SQS 메시지 삭제). 실제 동작: ENT4000 이 whitelist 를 통과하지 못해 HttpError 로 rethrow → run() catch → error 레벨 로그 + updateErrorState 시도(자체적으로 다시 403 가능성).

Log Evidence#

Datadog 쿼리 (본 클러스터 재현):

text
service:cupixworks-any-mesh-agent status:error @environment:production "HTTP request failed"

24h 내 동일 패턴 확인:

text
service:cupixworks-any-mesh-agent status:error @environment:production

BIM 227 처리 시퀀스 (2026-07-15 15:17:24 KST, tight window):

text
15:17:24  warn  CupixAuth::handleError | Response statusCode: 403, requestUriHref: .../bims/227..., body.result: {"code":"ENT4000","type":"Cupix::Errors::NotFound","reason":"Bim not found"}
15:17:24  error MeshService::run | error: {"stack":"HttpError: HTTP request failed ... bimApi.js:1191:40 ...","statusCode":403,"name":"HttpError"}
15:17:24  error HTTP request failed
15:17:24  warn  BaseService::getApiErrorToDeleteMessage | error msg - {...,"modelId":227}
15:17:24  error BaseService::handlingMessageErrors | Error and message object - {...,"modelId":227,"sqsMessage":{"MessageId":"912c9efa-...","ApproximateReceiveCount":"1"}}
15:17:24  info  BaseService::cleanUpAnythingRelatedModel | path: /tmp/workspace/227

BIM 229 (같은 시간대, 다른 응답 경로) — ARG10002 로 조용히 종료:

text
15:16:15  warn  MeshService::createCPBimByBimId | end - reason: Bim not found

두 로그를 비교하면 ARG10002createCPBimByBimId 안에서 warn 으로 정리되지만 ENT4000 (본 클러스터) 는 상위 MeshService::run catch 까지 올라가 error 로 기록됨이 확인된다.

Hypotheses Considered#

# Hypothesis Evidence for Evidence against Verdict
H1 Tesla API 인증 만료/토큰 문제로 403 403 statusCode body.result 가 auth 오류가 아닌 Cupix::Errors::NotFound ENT4000. CupixAuth::handleError 도 body 를 그대로 통과시킴 Rejected
H2 Tesla API 서비스 outage / 네트워크 실패 HTTP request failed 문자열 statusCode 403 + 정상 JSON body 수신 → 서버가 응답한 명시적 4xx. 상태보드에도 dep:* 아님 (svc:cupixworks-any-mesh-agent::unknown) Rejected
H3 SQS 처리 지연 중 BIM 이 trash 로 이동, mesh-service 가 ENT4000 (trashed) 를 whitelist 하지 않아 error 로 승격 bodyResult.code=ENT4000 type=Cupix::Errors::NotFound reason="Bim not found" modelId=227; tesla base_repository.rb:352in_trash 일 때 ENT4000 반환; mesh-service mesh-service.ts:145ARG10002 만 검사; 자매 로그(BIM 229) 는 ARG10002 로 warn 종료 Confirmed
H4 ADF (Autodesk Forge) 관련 downstream 실패 Forge 도 호출됨 Stack trace 가 bimApi.js:1191 (tesla SDK) 이며 URI 는 api-tesla.cupix.internal/bims/227. Forge 호출 이전 단계 Rejected

Fix Recommendation#

즉시 조치 (Critical)#

  • 파일: applications/agents/packages/cupix-tesla-mesh-agent/src/mesh-service.ts:145
  • createCPBimByBimId 의 catch 블록에서 whitelist 를 ARG10002 뿐 아니라 ENT4000 도 포함하도록 확장한다. 두 코드 모두 tesla 측에서 Cupix::Errors::NotFound 로 통일된 semantic (부재/휴지통) 이므로 agent 관점에서는 동일하게 "skip" 처리하는 것이 안전.
  • 같은 파일 내 updateBimMeshState (line 156-163) 호출도 이후 run()updateErrorState (line 297-302) 에서 trashed BIM 을 mesh_state=error 로 업데이트하려다 재차 ENT4000 을 만날 수 있다. updateErrorState 의 catch 도 동일 whitelist 를 적용해야 error 로그 재발을 막을 수 있음.

단기 개선 (1주 이내)#

  • packages/api/src/authentication/cupix-auth.ts:42 handleError 는 현재 모든 4xx 를 warn 으로 남기지만 상위에서 다시 error 로 승격된다. tesla API 가 명시적으로 Cupix::Errors::NotFound body 를 리턴한 경우는 agent 공통 레벨에서 warn 으로 유지하도록 매핑 규칙을 정리 (base-service.ts getApiErrorToDeleteMessage 와 함께 통일).
  • 다른 agent 서비스(potree, forge, bim-revision, deviation-*) 도 동일 패턴을 공유한다면 base 레이어에 TeslaNotFoundCodes = ['ARG10002', 'ENT4000'] 을 상수화하여 재사용.

장기 개선 (재발 방지)#

  • SQS enqueue 이후 실 처리까지 시간차가 존재하는 한 "leftover trashed job" 은 지속 발생한다. tesla 측에서 BIM soft-delete 시 mesh 관련 in-flight SQS 메시지를 정리하거나, agent 가 실행 초입에서 trash 상태를 정상 종료 케이스(정보 로그 + SQS ack)로 분류하는 정책을 문서화.

Monitoring#

핵심 monitor 쿼리 (release dashboard timeseries widget 그대로 사용):

text
service:cupixworks-any-mesh-agent status:error @environment:production "HTTP request failed"

ENT4000 만 좁혀서 재발 여부 확인:

text
service:cupixworks-any-mesh-agent status:error @environment:production "ENT4000"

트레이싱용 (warn 레벨, upstream context):

text
service:cupixworks-any-mesh-agent status:warn @environment:production "CupixAuth::handleError"

Risk Assessment#

  • Risk level: low
  • 예상 복잡도: trivial (whitelist 코드 추가 1-2 줄 + spec)