ES /docs

ImageCPObject::downloadFile | response path: /tmp/workspace/cl05fno4p2re/cl05fno4p2re.png, code: 404

RCA: ImageCPObject::downloadFile | response path: /tmp/workspace/cl05fno4p2re/cl05fno4p2re.png, code: 404

Error Log#

Datadog Logs

text
ImageCPObject::downloadFile | response path: /tmp/workspace/cl05fno4p2re/cl05fno4p2re.png, code: 404, message: Not Found

Impact#

  • Service: cupixworks-any-thumbnail-agent
  • Team: tpc
  • 발생 횟수: 1
  • 최초 발생: 2026-04-11T04:41:19.293Z
  • 최근 발생: 2026-04-11T04:41:19.293Z

Root Cause Summary#

CPAttachment.setModel() 에서 attachable type 문자열을 API URL 경로로 변환할 때 CamelCase → snake_case 변환 없이 단순히 .toLowerCase() + 's'를 적용합니다. RevisionRequest 타입의 경우 revisionrequests가 생성되지만, Rails 라우트는 revision_requests (snake_case)를 사용합니다. 이로 인해 썸네일 에이전트가 첨부파일 원본을 다운로드할 때 잘못된 URL 경로로 요청하여 API가 404를 반환합니다. 단일 단어 타입(Annotation, Texture)은 정상 동작하지만, 복합 단어 타입(RevisionRequest, WorkItem)은 모두 동일한 문제를 가지고 있습니다.

Technical Analysis#

Code Path#

  • Entry point: thumbnail-service.ts:58ThumbnailService.run() 이 SQS 메시지를 받아 실행
  • thumbnail-service.ts:94-103newModel() 에서 params.type"Attachment"이면 CPAttachment 인스턴스 생성
  • thumbnail-service.ts:75supportModel.setModel() 호출
  • Failure point: cpattachment.ts:38 — attachable type을 URL 경로로 변환하는 로직
typescript
// cpattachment.ts:37-40
const attachableId = this.modelAttachable.id.toString();
const attachableType = this.modelAttachable.type.toLowerCase() + 's';

const baseEndPoint = Environment.CPX_API_ENDPOINT + '/' + attachableType + '/' + attachableId + '/attachments/' + this.modelKey;

attachable.type"RevisionRequest"인 경우:

  • 기대 동작: revision_requests (Rails snake_case 라우트와 일치)
  • 실제 동작: revisionrequests (CamelCase를 단순 lowercase, underscore 누락)

생성된 URL: http://api-tesla.cupix.internal/api/v1/revisionrequests/10/attachments/cl05fno4p2re/download 정상 URL: http://api-tesla.cupix.internal/api/v1/revision_requests/10/attachments/cl05fno4p2re/download

  • thumbnail-service.ts:77supportModel.downloadOriginal() 호출
  • image-cpobject.ts:164-178downloadOriginal() 에서 _downloadOriginalFileUrl 사용하여 다운로드 시도
typescript
// image-cpobject.ts:164-178
downloadOriginal = async (): Promise<void> => {
	logger.debug('ImageCPObject::downloadOriginal | begin');
	logger.info('ImageCPObject::downloadOriginal | url: %s, path: %s', this._downloadOriginalFileUrl, this._originalFilePath);
	if (this._downloadOriginalFileUrl == undefined || this._originalFilePath == undefined) {
		logger.error('ImageCPObject::downloadOriginal | end - undefined url or path');
		return;
	}
	// ...
	await this.downloadFile(this._downloadOriginalFileUrl, this._originalFilePath);
};
  • image-cpobject.ts:73-77downloadFile() 에서 응답 status code 404 수신, 에러 로그 출력
typescript
// image-cpobject.ts:73-77
sendReq
	.on('response', res => {
		if (res.statusCode !== 200) {
			logger.error('ImageCPObject::downloadFile | response path: %s, code: %d, message: %s', filePath, res.statusCode, res.statusMessage);
			reject(cupixAuth.handleError(res));
		}
	})

Rails 라우트는 revision_requests만 인식합니다:

ruby
# tesla/config/routes.rb:1840-1842
resources :revision_requests, only: %i[create] do
  concerns :attachments
end

Log Evidence#

사용한 Datadog 쿼리:

text
service:cupixworks-any-thumbnail-agent "cl05fno4p2re"
Time range: 2026-04-11T03:41:00Z to 2026-04-11T05:11:00Z
text
"cl05fno4p2re"
Time range: 2026-04-11T03:41:00Z to 2026-04-11T05:11:00Z

이벤트 타임라인:

시간 (KST) 이벤트 서비스
13:38:07 Attachment cl05fno4p2re 생성 (model_id: 27536, attachable: RevisionRequest#10) event-service
13:38:08 POST /api/v1/revision_requests/10/attachments/cl05fno4p2re/upload_url → 200 cupixworks-api
13:38:12 PUT /api/v1/revision_requests/10/attachments/cl05fno4p2re/check_uploading → 200 cupixworks-api
13:41:19 ImageCPObject::downloadOriginal — URL: .../revisionrequests/10/attachments/cl05fno4p2re/download thumbnail-agent
13:41:19 [404] GET /api/v1/revisionrequests/10/attachments/cl05fno4p2re/download (ApiController#routing_error) cupixworks-api
13:41:19 ImageCPObject::downloadFile — code: 404, message: Not Found thumbnail-agent
13:41:20 [200] GET /api/v1/annotations/10/attachments/cl05fno4p2re — 정상 조회 (다른 경로) cupixworks-api

핵심 로그:

썸네일 에이전트가 잘못된 URL로 다운로드를 시도한 info 로그:

text
ImageCPObject::downloadOriginal | url: http://api-tesla.cupix.internal/api/v1/revisionrequests/10/attachments/cl05fno4p2re/download, path: /tmp/workspace/cl05fno4p2re/cl05fno4p2re.png

API 서버에서 해당 경로를 routing_error로 처리한 로그:

text
[404] GET /api/v1/revisionrequests/10/attachments/cl05fno4p2re/download (ApiController#routing_error)

업로드 시에는 정상 경로(revision_requests)를 사용하여 성공한 로그:

text
[200] POST /api/v1/revision_requests/10/attachments/cl05fno4p2re/upload_url (Api::V1::AttachmentsController#upload_url)
[200] PUT /api/v1/revision_requests/10/attachments/cl05fno4p2re/check_uploading (Api::V1::AttachmentsController#check_uploading)

Attachment 생성 이벤트에서 확인된 모델 정보:

json
{
  "key": "cl05fno4p2re",
  "name": "스크린샷 2026-04-11 오후 1.37.55.png",
  "attachment_type": null,
  "state": "created",
  "model_type": "Attachment",
  "model_id": 27536
}

Fix Recommendation#

즉시 조치 (Critical)#

  • 수정 파일: applications/agents/packages/cupix-tesla-thumbnail-agent/src/model/cpattachment.ts:38
  • attachable.type을 URL 경로로 변환할 때 CamelCase → snake_case 변환을 적용해야 합니다. "RevisionRequest""revision_request""revision_requests", "WorkItem""work_item""work_items" 형태로 변환해야 Rails 라우트와 일치합니다.
  • 현재 this.modelAttachable.type.toLowerCase() + 's' 부분을 CamelCase를 snake_case로 변환하는 로직으로 교체하면 됩니다 (예: 대문자 앞에 _ 삽입 후 전체 lowercase).

단기 개선 (1주 이내)#

  • 다른 attachable type들도 동일한 패턴인지 검증이 필요합니다. WorkItem, RevisionRequest 등 복합 단어 타입이 모두 영향을 받으며, 이들의 attachment 썸네일 생성이 모두 실패할 수 있습니다.
  • upload 경로(upload_url, check_uploading)가 정상 동작하는 것으로 보아, upload 쪽은 다른 코드 경로를 사용하거나 API client가 올바른 경로를 생성하고 있을 수 있습니다. upload 경로와의 일관성을 확인해야 합니다.

장기 개선 (재발 방지)#

  • API endpoint URL을 각 모델에서 직접 문자열 조합으로 생성하는 대신, API client 라이브러리에서 중앙 관리하도록 리팩토링하는 것을 고려할 수 있습니다.
  • attachable type → URL path 매핑을 명시적 매핑 테이블로 관리하면 타입 추가 시 실수를 방지할 수 있습니다.

Monitoring#

  • 추가할 메트릭/알림: cupixworks-any-thumbnail-agent 서비스에서 downloadFile 404 에러 발생 시 알림
  • Datadog 쿼리:
text
service:cupixworks-any-thumbnail-agent status:error "downloadFile" "404"

Risk Assessment#

  • Risk level: medium
  • 예상 복잡도: trivial — cpattachment.ts:38 한 줄 수정으로 해결 가능