Mobidoo

오류와 비용

이 문서는 영문 원고를 AI로 번역한 내용이라 표현이 어색할 수 있습니다.

API의 모든 오류는 같은 봉투를 쓰고, 모든 코드는 분기할 수 있는 소문자 토큰입니다. 이 페이지는 Formats 표면의 코드 전부를 한 곳에 모아, 언제 발생하는지로 묶었습니다. run이 생기기 전, run을 읽는 동안, run 자체가 실패할 때, 웹훅을 전달하지 못했을 때. 비용과 요청 한도는 끝에 있습니다.

오류 봉투

필드용도
codeswitch로 분기할 안정적인 토큰. ^[a-z0-9_]+$이며, 문장이 오지 않습니다.
message사람이 읽는 문장이며 바뀔 수 있습니다. 로그에는 남기되, 매칭하지 마세요.
request_idx-sume-request-id 헤더로도 옵니다. 지원 요청 시 인용하세요.
retryable, retry_after_seconds같은 요청을 다시 보내면 성공할 수 있는지, 먼저 얼마나 기다릴지.
next_actionauthenticate, fix_input, add_funds, retry_later, poll_status, contact_support, none 중 하나.
category, stage, public_reason대시보드와 알림용 큰 분류.
details코드별 상세: required_scope, workspace_id, violations[], index, status, scope 등. 아래 코드마다 적었습니다.

HTTP status로 먼저 분기하고, 그다음 code로 분기하세요. 생성 시점의 4xx는 아무것도 실행되지 않았고 아무것도 청구되지 않았다는 뜻이므로, 재시도가 아니라 호출을 고쳐야 합니다. 403 insufficient_scope를 루프에서 재시도하는 것이 가장 흔하고 가장 비싼 실수입니다.

생성 시 오류

POST /v1/formats/{handle}/{slug}/runsPOST …/bulk-runs. 아무것도 실행되지 않고, 청구도 없으며, 실패한 생성은 Idempotency-Key를 풀어 줍니다.

Statuserror.code의미대응
400invalid_request본문에 instruction / input / previous_run_id / attachments 중 하나도 없음; output_schemaresponse_format을 둘 다 보냄; input이 object가 아니거나 최상위 키가 64개를 넘거나 2 MiB를 넘음; generation_spend_cap_usd0이거나 500 초과; model이 카탈로그에 없음; bulk 본문의 concurrency 또는 items가 잘못됨; 웹훅 URL이 공개 HTTPS가 아님; communication alias가 서로 충돌.messagedetails를 읽으세요.
400unknown_parameterAPI가 모르는 최상위 필드. thread_id도 여기 해당합니다. details.errors[].suggestion이 의도했을 필드를 알려 줍니다.이름을 고치거나 제거하세요.
400output_schema_invalid스키마가 지원 subset 밖입니다. details.violations[]에 모든 { path, rule, message }가 나열됩니다.위반 항목을 각각 고치세요. 지원 스키마를 참고하세요.
400invalid_attachmentattachments[] 항목이 잘못됐거나, attachments[]input URL이 공유하는 미디어 예산을 넘었습니다.Format API의 attachment 오류를 참고하세요.
400attachment_not_found이 워크스페이스에 없는 asset_id.업로드하거나 URL을 쓰세요.
400previous_run_format_mismatchprevious_run_id가 다른 Format에서 만들어진 run입니다.그 Format에서 이어 가세요.
400previous_run_not_resumable그 run에는 이어 갈 것이 없습니다. detailsprevious_run_status, has_thread, artifact_count가 옵니다.새 run을 시작하세요.
401unauthorized키가 없거나, 형식이 잘못됐거나, 폐기됐거나, 다른 호스트의 키이거나, 자격 증명을 두 개 보냈습니다.헤더를 고치세요.
402insufficient_credits워크스페이스 지갑이 이 run을 감당할 수 없습니다. next_actionadd_funds.충전하세요. 충전 없이 재시도하면 같은 답이 옵니다.
402organization_wallet_not_provisioned지갑이 아직 준비되지 않은 조직 워크스페이스.관리자가 충전해야 합니다.
403insufficient_scope키에 formats:write가 없거나(details.required_scope), 서비스 계정 키입니다(details.reason: service_account_format_runs_unsupported).스코프를 가진 새 키를 만드세요. 기존 키에는 스코프를 추가할 수 없습니다.
403workspace_key_required팀 Format인데 개인 키입니다. details.workspace_id가 워크스페이스를 가리킵니다.그 워크스페이스에서 키를 만드세요.
404format_not_found모르는 handle이나 slug, 보관된 Format, 또는 키의 워크스페이스 밖 Format.주소와 키를 확인하세요.
404previous_run_not_foundprevious_run_id가 모르는 값이거나 내 것이 아닙니다.id를 확인하세요.
409format_inactiveFormat이 inactive입니다.대시보드에서 활성화하세요.
409format_api_trigger_disabled이 Format의 API 트리거가 꺼져 있습니다.대시보드에서 켜세요.
409format_run_in_progresson_active_run: "reject"인데 이미 진행 중인 run이 있습니다.기다리거나 reject를 빼세요.
409format_not_forkableFormat이 아니라 내장 capability를 주소로 썼습니다.Formats by Sume나 직접 만든 Format을 호출하세요.
409previous_run_not_terminal이어 가려는 run이 아직 실행 중입니다.폴링한 뒤 다시 호출하세요.
409idempotency_conflict같은 Idempotency-Key가 다른 본문으로 이미 쓰였습니다. bulk에서는 details.queue_id가 원래 큐를 가리킵니다.키 유도 방식을 고치세요. 그대로 재시도하지 마세요.
409idempotency_key_in_use같은 키의 다른 요청이 진행 중입니다. retryable: true.1초쯤 기다렸다가 다시 보내세요.
413payload_too_large요청 본문이 4 MiB를 넘습니다(details.limit_bytes).input을 줄이고, 미디어는 URL로 보내세요.
413attachment_too_large이미지 하나가 30 MB를 넘거나 전체가 500 MB를 넘습니다.크기를 줄이세요.
429rate_limited이 키의 write 예산을 다 썼습니다. error.details.scopewrite.retry-after만큼 기다리세요. 요청 한도를 참고하세요.
502attachment_fetch_failedSume가 attachment를 가져오지 못했습니다(details.index). 5xx이지만 입력 문제입니다: next_actionfix_input.URL을 공개적으로 접근 가능하게 만드세요.
503studio_agent_upstream_unavailableSume 쪽 장애.같은 Idempotency-Key로 나중에 재시도하세요.
4xx/5xxformat_run_failed_to_start더 구체적인 코드가 없는 이유로 run을 시작하지 못했습니다.message를 읽고 한 번 재시도한 뒤, request_id와 함께 지원에 문의하세요.

202가 나중에 위 오류로 바뀌는 일은 없습니다. receipt를 받은 뒤의 실패는 receipt 위에 status: "failed"로 옵니다.

읽기 시 오류

GET /v1/format-runs/{run_id}, /status, /result, /events, POST …/cancel, POST …/webhook/redeliver, GET /v1/format-run-queues/{queue_id}, 그리고 Format 읽기.

Statuserror.code의미대응
401unauthorized위와 같습니다.헤더를 고치세요.
403insufficient_scope읽기에는 formats:read, 취소와 redeliver에는 formats:write가 필요합니다.새 키를 만드세요.
404format_run_not_found모르는 run id이거나 다른 소유자의 run.id와 키를 확인하세요. 볼 수 없는 run은 존재하지 않는 run과 같게 읽힙니다.
404format_run_queue_not_found모르는 큐이거나 다른 소유자의 큐.같습니다.
404format_not_found위와 같습니다.같습니다.
409run_not_completedrun이 종료되기 전에 GET …/result를 호출했습니다. details.status가 현재 status이고, retry_after_seconds가 다음 폴링 시점을 제안합니다.status_url을 폴링한 뒤 result_url을 읽으세요.
409webhook_not_configuredwebhook_url 없이 만든 run에 redeliver를 호출했습니다.다시 보낼 것이 없습니다.
409run_not_terminalrun이 아직 실행 중인데 redeliver를 호출했습니다.종료 receipt를 기다리세요.
429rate_limitedread 예산을 다 썼습니다(details.scope: read).retry-after만큼 기다리세요. run은 계속 실행됩니다.
503studio_agent_upstream_unavailableSume 쪽 장애.재시도하세요. run은 계속 실행됩니다.

폴링 루프 안의 429503은 일시적입니다. 루프를 포기해도 run이나 그 비용은 멈추지 않으니, 물러났다가 다시 폴링하세요.

run 자체가 실패할 때

끝내지 못한 run은 status: "failed", error: { code, message }, 그리고 대개 더 자세한 output_error와 함께 돌아옵니다. artifacts[]에는 run이 생성한 모든 것이 여전히 나열되고, output에는 스키마를 만족한 부분 결과가 그대로 실립니다. 실패가 절대 받지 못하는 것은 포인터입니다. primary_output_urlnull이므로 if (run.primary_output_url)은 "완성본이 존재한다"의 안전한 검사로 남습니다.

error.code의미대응
unattended_blocked사람 없이는 넘을 수 없는 게이트에 걸렸습니다. 브리프에 맞는 아바타가 없거나, 채팅이었다면 물어봤을 입력이 빠진 경우. message는 그대로 보여 줘도 되게 쓰여 있습니다.입력이나 브리프를 고치고, 새 Idempotency-Key로 재시도하세요.
output_schema_unsatisfiedrun은 끝났지만 결과가 output_schema에 맞지 않았거나, 만들지 않은 미디어를 참조했습니다. details.rejected_urls[] 또는 details.violations[], 그리고 미디어 종류별 harvested 수.details.harvested를 스키마의 필수 항목과 비교하세요. 대개 Format이 만들지 않는 파일을 요구하는 스키마입니다. nullable로 풀거나 instruction을 바꾸세요.
deliverable_missingFormat이 미디어를 만든다고 선언했는데(io.output_kind) 이 run은 하나도 만들지 않았습니다.재시도하세요. 반복되면 입력이 레시피가 기대하는 것이 아닙니다.
primary_output_missing결과는 스키마를 만족했지만, 지정한 primary_output_key가 비어 있습니다. output에 부분 결과가 실립니다.run을 이어 가서 빈 곳을 채우거나 재시도하세요.
agent_reported_failurerun 자신이 제출한 return_format_output이 "전달하지 못했다"고 말했습니다. 명시적 실패 payload, failed / stand-in으로 표시된 미디어 슬롯, 또는 Format이 선언한 산출물이 아닌 primary(video 키 아래의 오디오나 정지 이미지). output에는 실제로 만들어진 것의 ledger가 실리고 primary_output_url은 null입니다.details.reasonoutput을 읽으세요. output의 클립은 실제 결과이며 재시도해도 다시 생성되지 않습니다. run을 이어 가거나 새 Idempotency-Key로 다시 실행하세요.
incomplete_assembly생성 job이 아직 끝나지 않은 채 run이 시간 한도에 닿아, 전달된 미디어가 지불한 전부가 아닙니다. details.pending_job_countdetails.pending_jobs[]가 그 job들을 가리키고, 스키마가 허용하면 부분 ledger가 output에 실립니다.previous_run_id로 run을 이어 가세요. 끝난 클립은 스레드에 있고 다시 생성되지 않습니다.
output_extraction_failed투영 자체를 실행하지 못했습니다. details.reason: harvest_unavailable은 run이 마무리되는 동안 미디어를 읽지 못했다는 뜻이며, statuscompleted로 남고 다음 읽기에서 receipt가 채워집니다. details.reason: harvest_threw는 run이 끝난 뒤 호스트의 harvest 자체가 크래시했다는 뜻입니다. run은 failed가 되고 details.thrown에 던져진 프레임과 빌드가 실리며, ledger에 Format이 선언한 미디어가 하나도 없는 run은 대신 deliverable_missing을 보고합니다.harvest_unavailable: run을 한 번 더 읽고, 계속되면 새 키로 재시도하세요. harvest_threw: 호스트 결함입니다 — run id를 알려 주세요. 스레드의 클립은 실제 결과이며 재시도해도 다시 생성되지 않습니다.
mcp_unavailable이 run에 필요한 턴별 Sume MCP 도구가 붙지 않아, 도구 없는 턴을 실행하는 대신 호스트가 모델 실행 전에 run을 실패시켰습니다(#7378). details.retryabletrue, details.chargedfalse입니다 — 생성이 실행되지 않았고 과금도 없습니다.Idempotency-Key로 재시도하세요. 반복되면 요청이 아니라 도구가 다운된 것입니다.
provider_unavailable모델 제공자 스트림이 끊기고 재연결 횟수를 다 쓴 뒤에도 run이 완성본을 만들지 못했습니다. 입력 때문이 아닙니다. details.retryabletrue입니다.Idempotency-Key로 재시도하세요. 끝난 클립은 스레드에 있고 다시 생성되지 않습니다.
format_run_failed일반 실패.message를 읽으세요. cap을 넘어 쓰려던 run도 여기로 오므로, 브리프를 키우기 전에 usage.billable_amount_usd_microsusage.generation_spend_cap_usd_micros를 비교하세요.

이 집합은 열려 있다고 보세요. 새 코드가 추가될 수 있으니 아는 것만 처리하고 나머지는 그대로 통과시키세요. 실패한 run은 Idempotency-Key로 재시도하세요. 옛 키는 이미 받은 receipt에 묶여 있습니다. 실패가 클립을 남겼다면 새 run보다 run 이어 가기를 택하세요.

웹훅으로는 같은 run이 status: "ERROR", outcome: "error", 그리고 payload.error.code를 그대로 비추는 error.code와 함께 도착합니다. 완료됐지만 스키마를 채우지 못한 run은 status: "OK", outcome: "degraded"로 도착합니다. 실제 미디어는 있고, outputnull입니다.

웹훅 전달 실패

전달 결과는 run을 절대 바꾸지 않습니다. 모든 receipt의 webhook_delivery 블록이 무슨 일이 있었는지 말해 줍니다.

webhook_delivery.status의미대응
retrying시도가 실패했고 next_attempt_at이 다음 시도 시각입니다. 엔드포인트의 HTTP 429/503Retry-After를 최대 1시간까지 존중합니다.last_status_code가 고칠 수 있는 것이 아니라면 할 일이 없습니다.
failed, exhausted열 번의 시도가 거부되거나, 시간 초과(각 10초)되거나, 리다이렉트되거나, URL이 재검증에 실패했습니다. last_status_codelast_error가 이유를 말합니다.result_url에서 receipt를 읽고, 엔드포인트를 고친 뒤 POST …/webhook/redeliver로 다시 보내세요.
payload: null인 봉투receipt가 1 MiB를 넘었습니다. error.codepayload_too_large이고 error.result_url이 가져올 곳을 말합니다. status는 여전히 run의 실제 결과를 보고합니다.result_url을 가져오세요. payload가 object라고 가정한 handler는 가장 큰 run에서 터집니다.

전체 전달 규칙: 실행과 결과.

크레딧과 비용

run은 키가 속한 워크스페이스에서 비용을 씁니다. 두 개의 게이트가 서로 다른 시점에 적용됩니다.

게이트시점실패 시
지갑생성 시. 워크스페이스가 run을 감당할 수 있어야 합니다.402 insufficient_credits(next_action: add_funds) 또는 402 organization_wallet_not_provisioned. 아무것도 실행되지 않았습니다.
Spend caprun 도중. run은 유효 cap을 넘어 쓸 수 없습니다.run이 failed로 끝나고, usage가 cap에 얼마나 가까웠는지 보여 줍니다.

cap은 여러분이 쥔 제어 수단입니다. 모든 Format이 cap을 하나 갖고 있고(Format의 generation_spend_cap_usd_micros; 지정한 적이 없으면 $400), 요청의 generation_spend_cap_usd가 이 run만의 천장을 플랫폼 최대 $500까지 지정합니다. Format cap보다 큰 값도 그대로 적용되고, null은 $500으로 실행하며, 0은 거부됩니다. 프로덕션의 긴 영상 run은 보통 $120 안팎의 cap으로 만들어지고, 씬 하나 재시도는 몇 달러면 됩니다. 자세한 내용: Spend caps.

청구되는 것은 계량된 생성(영상, 이미지, 아바타, 음성, 타임라인 작업)이며, API 요금 페이지의 요율을 따릅니다. receipt는 이것을 usage.billable_amount_usd_micros로 보고합니다. run이 진행되는 동안 올라가고, 예약된 금액과 확정된 금액을 모두 세며, run이 종료되면 정산됩니다. 에이전트 자체의 LLM 턴은 제외되므로 run의 총비용은 아니고, 청구서가 아니라 receipt 숫자입니다. GET /v1/usageGET /v1/balance가 청구 기록입니다. usagenull이면 비용을 읽지 못한 것이며, 0과는 다릅니다.

취소나 실패 전에 끝난 생성은 청구되며, 뒤 단계가 실패해도 환불되지 않습니다. 생성 시점의 4xx, 멱등 200 재생, skipped run은 비용이 들지 않습니다.

요청 한도

모든 키는 워크스페이스 플랜에 따라 /v1 전체에 걸친 분당 요청 예산을 갖습니다. 읽기와 쓰기는 예산이 분리되어 있고, 읽기는 쓰기 숫자의 40배를 받으므로 폴링이 여러분의 생성 요청을 굶기지 않습니다.

플랜분당 쓰기분당 읽기
Free1204800
Pro30012000
Startup60024000
Scale120048000
Enterprise계약값. 준비 전까지는 Scale계약값

읽기는 모든 GET입니다. receipt, status_url, events_url, result_url, Format과 run 목록. 쓰기는 나머지 전부입니다. run과 큐 생성, 취소, redeliver.

모든 응답에 현재 상태가 실리고, 429는 어느 예산에서 나왔는지 알려 줍니다.

헤더의미
ratelimit-limit이 요청이 쓴 예산 기준으로, 현재 창에서 허용되는 요청 수.
ratelimit-remaining그 창에 남은 요청 수.
ratelimit-reset창이 초기화되기까지의 초.
retry-after429에 실리는 대기 초. error.details.scoperead 또는 write.

직접 요청을 세지 말고 헤더에 맞춰 속도를 조절하세요. 요청 속도는 생성 용량이 아닙니다. 동시에 실행되는 생성 수는 플랜의 concurrency 한도가 정하며, 요청 속도를 올려도 늘어나지 않습니다.

도움 받기

모든 응답에 x-sume-request-id가, 모든 receipt에 request_id가 실립니다. 문의할 때 이 값과 run id, error.code를 인용하세요. API 키, 서명 시크릿, 원본 미디어 URL은 보내지 마세요.

다음