Skip to main content
오류는 서로 다른 두 곳에서, 서로 다른 두 가지 어휘로 나타납니다:
  • API 요청 오류 — 동기 API 호출에 대한 HTTP 응답입니다(인증, 결제, 잘못된 형식의 요청, 존재하지 않는 리소스 등). API 요청 오류를 참고하세요.
  • Prediction 실패 코드 — 요청은 접수되어 대기열에 들어갔지만, prediction 자체가 status: "failed"로 끝난 경우입니다. 실패 내용은 prediction의 error 객체로 설명되며, prediction 상태 엔드포인트, webhook 전달, 그리고 result 엔드포인트를 통해 받을 수 있습니다. Prediction 실패 코드를 참고하세요.

Prediction 실패 코드

실패한 prediction은 error 객체를 담고 있습니다:
실패한 prediction에는 요금이 청구되지 않으며, 해당 요청을 위해 예약된 크레딧은 반환됩니다. 실패하지 않은 prediction은 error: null을 담고 있습니다. 2026년 8월 17일 이전에 연동하셨다면 마이그레이션 안내를 참고하세요.

오류가 전달되는 곳

같은 error 객체가 모든 채널에 게시되므로, 평소에 보던 곳에서 그대로 읽으면 됩니다:

result 엔드포인트에서 실패 읽기

이미 실패한 prediction의 출력을 요청하면, 그 원인이 된 실패를 담은 400이 반환됩니다. 요청 수준의 코드는 PREDICTION_FAILED입니다:
두 수준에 두 개의 code가 있으며, 둘은 같은 어휘가 아닙니다:
  • error.codePREDICTION_FAILED로, “출력을 요청한 그 prediction이 출력을 만들어 내지 못했다”는 뜻의 API 요청 오류입니다.
  • error.details는 prediction 자체의 error 객체입니다 — 같은 요청에 대해 /status가 보고하는 내용과 동일하므로, 두 엔드포인트가 실패 원인을 두고 서로 다른 말을 할 수 없습니다. 분기는 error.details.reasonerror.details.retryable로 하세요.
error.message는 prediction의 message를 그대로 반복하므로, 최상위 message만 읽는 클라이언트도 쓸모 있는 정보를 얻습니다. 두 개의 timestamp, 두 가지 의미. 최상위 timestamp는 이 HTTP 응답이 생성된 시각이고, error.details.timestamp는 prediction이 실패한 시각입니다. 며칠 뒤에 가져오는 prediction이라면 둘은 며칠 차이가 납니다. 실패 시점을 뜻할 때는 언제나 안쪽 값을 읽으세요. 공식 클라이언트 라이브러리가 이 작업을 대신 해 줍니다: result()가 던지는 오류의 code, reason, retryable은 prediction 자체의 값이며, 같은 실패에 대해 subscribe()가 던지는 것과 동일합니다. 아직 대기열에 있거나 실행 중인 prediction, 또는 취소된 prediction은 지금까지와 똑같은 일반적인 400을 계속 반환합니다.

재시도 여부 판단하기

retryable을 보세요. 이 필드는 단 하나의 질문 — 완전히 동일한 요청을 다시 보내면 결과가 달라질 수 있는가? — 에만 답하며, code와는 독립적입니다. 같은 code라도 어떤 실패에서는 재시도할 수 있고 다른 실패에서는 그렇지 않을 수 있습니다. retryable은 선택 필드입니다. 없을 때는 아래 표의 code별 기본값으로 대체하세요. 이 필드가 생기기 전 Sunra의 동작이 바로 그것이므로 기본값으로 대체하는 것은 언제나 안전하며, 다만 덜 정밀할 뿐입니다.

code

reason

reasoncode 뒤에 있는 구체적인 원인을 가리킵니다. 지표 집계, 라우팅, 기술 지원 진단에 사용하세요. 재시도 결정에는 retryable을 사용하세요. 현재 공개된 모든 reason에는 아래에 각각의 절이 있으며, 그 앵커는 reason 자체 — #input_fetch_failed, #moderation_blocked 등 — 이므로 오류 보고서에서 그 의미로 바로 링크할 수 있습니다.

input_validation_failed

code: invalid_input · retryable: false 요청이 Sunra 자체의 스키마 또는 파라미터 검증을 통과하지 못했습니다. message가 문제가 된 필드를 지목합니다. 대처 방법: 지목된 필드를 고치세요. 같은 요청은 계속 실패합니다.

provider_rejected_input

code: invalid_input · retryable: false 모델 공급자가 하나 이상의 입력 파라미터를 거부했습니다. 공급자가 어떤 파라미터인지 알려주면 message에 그대로 전달되며, 일부 공급자는 입력을 받아들일 수 없다는 사실만 알려줍니다. 그런 경우에는 추측하지 않고 그대로 그렇게 전달합니다. 대처 방법: 모델의 스키마와 대조해 파라미터를 점검하세요 — 범위를 벗어난 값, 지원되지 않는 조합, 모델이 받아들이지 않는 화면 비율이나 길이 등입니다.

input_fetch_failed

code: invalid_input · retryable: false 또는 true URL로 지정한 입력 파일을 가져오지 못했습니다. retryable이 실제로 달라지는 유일한 reason이므로, 짐작하지 말고 필드를 읽으세요:
  • false — 상대 호스트가 저희를 거부한 경우: 4xx, 저희가 가져올 수 없는 주소, 리다이렉트, 또는 크기 제한을 넘는 파일.
  • true — 상대 호스트에 일시적으로 도달할 수 없었던 경우: 5xx, 타임아웃, 또는 DNS 실패.
어떤 입력이 실패했는지 알 수 있도록 message에 제출한 URL이 그대로 표시됩니다. 다만 query string은 제거되므로 presigned URL에 담긴 자격 증명이 되돌아오는 일은 없습니다:
대처 방법: retryablefalse이면 해당 URL이 공개적으로 접근 가능한지, presigned 링크가 만료되지 않았는지 확인하세요. true이면 다시 시도하세요.

moderation_blocked

code: unsafe_content · retryable: false 모델 공급자의 콘텐츠 안전 시스템에 의해 차단되었습니다 — 들어가는 프롬프트와 입력 미디어일 수도, 돌아오는 생성 결과일 수도 있습니다. 대처 방법: 프롬프트나 미디어를 바꾸세요. 같은 내용을 다시 보내면 또 차단됩니다.

provider_rate_limited

code: service_provider_error · retryable: true 모델 공급자가 요청에 속도 제한을 걸고 있습니다. 대처 방법: 백오프를 두고 재시도하거나 다른 모델로 라우팅하세요.

provider_unavailable

code: service_provider_error · retryable: true 모델 공급자가 요청을 처리하지 못했습니다. 대처 방법: 나중에 재시도하거나 다른 모델로 라우팅하세요.

provider_timeout

code: task_timeout · retryable: true prediction이 허용된 시간 안에 완료되지 않았습니다. 대처 방법: 재시도하세요 — 부하가 낮은 시간대이거나, 요청을 더 작게(더 짧은 길이, 더 낮은 해상도) 하면 성공 확률이 올라갑니다.

provider_account_error

code: internal_server_error · retryable: false 해당 모델 공급자에 대한 저희 계정에 문제가 있습니다 — 결제, 자격 증명, 또는 영구 할당량입니다. 이는 저희 쪽 문제이지 입력의 문제가 아닙니다. 대처 방법: 사용자 쪽에서 하실 일은 없습니다. 재시도해도 소용이 없으며, 저희에게 자동으로 알림이 전달됩니다. 지금 당장 그 처리량이 필요하다면 다른 모델로 라우팅하세요.

endpoint_misconfigured

code: internal_server_error · retryable: false 이 모델 엔드포인트가 저희 쪽에서 잘못 설정되어 있습니다. 대처 방법: 사용자 쪽에서 하실 일은 없습니다. 재시도해도 소용이 없으며, 저희에게 자동으로 알림이 전달됩니다. 급한 경우 request_id와 함께 지원팀에 문의하세요.

queue_enqueue_failed

code: internal_server_error · retryable: true prediction을 대기열에 넣지 못했습니다. 대처 방법: 요청을 다시 제출하세요.

reaped_stalled

code: internal_server_error · retryable: true prediction이 멈춰 있다가 종료되었습니다. 대처 방법: 요청을 다시 제출하세요.

알 수 없는 값

codereason은 모두 열린 집합입니다. 저희가 더 많은 실패를 분류해 나가면서 새로운 값이 breaking change 공지 없이 추가됩니다. 여러분의 연동 코드는 인식하지 못하는 값을 만나더라도 크래시하거나, 오류를 버리거나, payload 전체를 거부해서는 안 됩니다.
  • 알 수 없는 reasonreason이 없는 것으로 간주하고 retryable(또는 code별 기본값)로 판단하세요. 원본 값은 로그에 남겨 두세요. 지원팀이 실패를 특정하는 가장 빠른 단서입니다.
  • 알 수 없는 codeinternal_server_error로 간주하세요. 이름을 알아 둘 만한 센티널 값이 하나 있습니다. unknown_error_code는 prediction이 실패했지만 그에 대한 분류를 전혀 복원할 수 없을 때 Sunra가 내보내는 값입니다.

마이그레이션 안내: 오류가 없을 때 errornull입니다

2026년 8월 17일부터 적용됩니다. error 객체는 모든 채널에서 하나의 표현만 갖습니다. 채널 사이에 있던 세 가지 차이는 사라졌습니다:
  • prediction이 실패하지 않았을 때 errornull입니다. GET /v1/predictions/{prediction_id}는 이전에는 succeeded, queued, cancelled 상태의 모든 prediction에 대해 빈 객체 "error": {}를 반환했습니다. 이제는 "error": null을 반환하며, 이는 queue status 엔드포인트가 이미 해 오던 방식입니다. 비어 있는지를 검사하고 있다면(Object.keys(response.error).length === 0), null 검사(response.error === null)로 바꾸세요.
  • 실패에는 언제나 비어 있지 않은 codemessage가 함께 옵니다. 실패가 기록한 내용을 저희가 분류할 수 없는 경우, 없거나 비어 있거나 문자열이 아닌 필드 대신 센티널 값 unknown_error_code와 일반적인 message를 받게 됩니다.
  • 일반 텍스트로 기록된 실패도 텍스트 그대로 전달됩니다. 2026년 4월의 일부 prediction은 오류를 문자열 하나로만 저장했습니다. GET /v1/predictions/{prediction_id}는 이전에는 그것을 버렸고, queue status 엔드포인트는 센티널 message로 대체했습니다. 이제는 두 곳 모두 그 내용을 code: "unknown_error_code" 아래의 message로 게시합니다.
삭제된 것도, 새로 생긴 필드도 없습니다: error는 이미 위의 모든 응답에 들어 있었고, 바뀐 것은 그 값뿐입니다. Webhook 전달은 그대로입니다 — 다른 채널들이 수렴해 간 형태가 바로 webhook의 형태였습니다 — 그리고 succeeded 전달에서 error는 여전히 null로 보내지지 않고 아예 없습니다. 호환 기간. 이중 발행 기간은 없습니다. 해당 날짜부터 API는 "error": {}를 더 이상 만들어 내지 않습니다. 그 이전에 수집한 payload를 재생하거나 다시 처리한다면, 그 저장 데이터가 모두 소진될 때까지 null{}를 같은 것으로 취급하세요.

예정된 변경: 일부 실패에 더 구체적인 code가 부여됩니다

현재 상당수의 실패가 service_provider_error로 보고되고 있으며, 그중에는 일시적이지도 않고 공급자 잘못도 아닌 경우가 많습니다. 저희가 공급자를 하나씩 분류해 나가면서 그런 실패들은 실제로 그것을 설명하는 code로 옮겨 갑니다:
  • 공급자가 결정론적으로 입력을 거부한 경우는 invalid_input이 됩니다(이전에는 service_provider_error);
  • 잘못 설정된 엔드포인트나 저희의 공급자 계정 문제처럼 Sunra 측 문제는 internal_server_error가 됩니다(이전에는 service_provider_error);
  • 가져오지 못한 입력 파일은 invalid_input이 됩니다(이전에는 internal_server_error).
이름이 바뀌거나 삭제되는 코드는 없으며 새로운 code 값이 도입되지도 않습니다. 위의 다섯 값은 여전히 분류된 코드의 전체 집합입니다. 바뀌는 것은 특정 실패가 그중 어떤 값을 받는가이며, 공급자 단위로 점진적으로 바뀝니다. 코드에서 code로 분기하고 있다면, 지금이 그 로직을 retryablereason으로 옮기기에 좋은 시점입니다. 이 두 필드는 실패 자체를 직접 설명하며 이번 재분류의 영향을 받지 않습니다.

API 요청 오류