エラー
すべての業務コードの意味、対処法、そして再試行する価値のあるエラー。
呼び出しが失敗すると、レスポンスは問題の種類を表す数値(code)と、人が読むための説明文(msg)を返します。分岐には数値を使い、説明文は表示やログに使ってください。
レスポンスの外枠
{ "code": 40201, "msg": "Insufficient balance", "request_id": "req_…" }codeは業務コードです。200が成功で、それ以外は下の表にあります。- 失敗時には
dataフィールドがありません。例外は一部のアセットライブラリのエラーで、data.reasonが付きます。 - HTTP ステータスも正しく設定されます(
40201なら HTTP402)。どちらか一方で分岐し、混ぜないでください。より具体的なcodeをおすすめします。 request_idはX-Request-Idヘッダーにも入っています。サポートへの問い合わせ時に添えてください。
レスポンスがそもそも JSON でない場合(途中のネットワークが返した HTML やテキストのページなど)は、HTTP ステータスで処理し、本文の先頭をログに残してください。
エラー文の言語
msg と、失敗したタスクの errorMessage は既定で英語です。Accept-Language に en、ja、ko、de、fr、es、pt-BR、ru、it、pl のいずれかを付けるか、コンソールで API のエラー言語を設定すると、その言語で返ります。それ以外の言語は英語になります。エラーレスポンスには Content-Language が付きます。コードは言語によって変わりません。msg を解析してはいけない理由の一つです。
モデルが具体的な失敗理由(参照画像が読めない、など)を返した場合、errorMessage はその理由を英語のまま、内部情報を取り除いて伝えます。
一般的なコード
code | HTTP | 意味 | 再試行する? |
|---|---|---|---|
200 | 200 / 202 | 成功 | — |
400 | 400 | リクエストまたは input が不正。msg が問題点を示します | しない。直してから |
40003 | 400 | アップロードがチケットと合わない(サイズ、種類、内容) | しない。チケットを取り直して再アップロード |
40004 | 400 | リクエストは正しいが、モデルが今この設定の組み合わせに対応できない | しない。msg に書かれた設定を変える |
401 | 401 | キーがない、認識できない、または無効化済み(詳細) | しない |
403 | 403 | 許可されていない(権限を参照) | しない |
404 | 404 | 存在しない、または別のキーのもの | しない |
409 | 409 | 現在の状態と衝突している(再試行の判断) | 場合による |
40901 | 409 | 見積もりの期限切れ、または価格の変更 | 見積もり直す |
413 | 413 | リクエスト本文が大きすぎる | しない。インラインではなくアップロードで送る |
429 | 429 | リクエストが多すぎる | する。Retry-After のあとで |
500 | 500 | こちら側の障害 | する。間隔を空けて |
503 | 503 | 補助的なサービスが一時的に使えない | する。Retry-After のあとで |
残高と上限
code | HTTP | 意味 | 対処 |
|---|---|---|---|
40201 | 402 | このタスクの確保額に対してクレジットが足りない | クレジットを購入してから再送 |
40202 | 402 | キーの利用上限に達した | API コンソールで上限を上げるか、リセットを待つ |
権限
code | HTTP | 意味 | 対処 |
|---|---|---|---|
40301 | 403 | このキーではこのモデルを呼び出せない | キーの許可モデルに追加する |
40302 | 403 | 送信元がキーの IP 許可リストにない | アドレスを追加するか、制限を外す |
40303 | 403 | この地域ではサービスを提供していない | 回避できません |
40310 | 403 | アカウントのメールアドレスが未確認 | 登録メールのリンクを開く。確認後すぐキーが使えます |
有効なキーで単なる 403 が返る場合は、アカウントが現在 API を使えない状態です。request_id を添えてサポートに連絡してください。
モデルの利用可否
code | HTTP | 意味 | 再試行する? |
|---|---|---|---|
50301 | 503 | このモデルは今タスクを受け付けられない | する。時間をおくか別のモデルへ |
40004 | 400 | モデルは動いているが、この設定には対応できない | しない。設定を変える |
どちらもタスクを作らず、クレジットも確保しません。
タスクの失敗コード
受け付けたあとに失敗したタスクは state: "failed" になり、errorCode に次のいずれかが入ります。一覧は閉じています。これ以外の値は upstream_failed として扱ってください。
errorCode | 意味 | 再試行する? |
|---|---|---|
invalid_request | モデルがパラメーターを受け付けなかった | しない。直してから |
unsupported_combination | この設定の組み合わせには今は対応していない | しない。設定を変える |
content_rejected | モデルがこの内容を断った | しない。プロンプトや参照素材を変える |
invalid_asset | 参照ファイルが読めない、またはもう使えない | 再アップロードして新しいタスクを作る |
rate_limited | 生成サービスが混み合っていた | する。間隔を空けて |
upstream_unavailable | 生成が一時的に使えない | する。少し待って |
generation_failed | 生成は動いたが何も出力されなかった | 場合による。同じ入力は同じように失敗しがち |
timeout | 時間切れ | 場合による。短く、または低解像度で |
upstream_failed | その他 | する。間隔を空けて |
失敗したタスクは確保したクレジットを解放するので、費用はかかりません(ごく一部のモデルはコンテンツ上の拒否にも課金し、そのモデルのページに明記しています)。errorMessage は理由を文章で示します。分岐は errorCode だけで行ってください。
409 を再試行すべきとき
| ケース | 再試行する? |
|---|---|
同じ Idempotency-Key のリクエストが同時に届いた | する。少し待って同じキーで |
その Idempotency-Key が別のリクエストや別のキーで使われていた | しない |
| アップロードや出力がまだ処理中 | する。数秒後に |
まだ終わっていないタスクに jobs/retry | する。終了状態になってから |
成功済みのタスクに jobs/retry | しない。新しいタスクを作る |
| アップロードのチケットやファイルの期限切れ | しない。アップロードし直す |
再試行の書き方
もう一度送って成功しうるものだけを再試行し、Retry-After があればそれに従い、なければ指数バックオフで待ちます。
const RETRYABLE = new Set([429, 500, 503, 50301]);
async function call(path, init, attempts = 4) {
for (let i = 0; i < attempts; i++) {
const res = await fetch(`https://api.popnow.ai/api/v1${path}`, init);
if (!res.headers.get('content-type')?.includes('json')) {
throw new Error(`HTTP ${res.status}: ${(await res.text()).slice(0, 200)}`);
}
const body = await res.json();
if (body.code === 200) return body.data;
if (!RETRYABLE.has(body.code)) throw new Error(`${body.code} ${body.msg} (${body.request_id})`);
const wait = Number(res.headers.get('retry-after')) * 1000 || 2 ** i * 1000 + Math.random() * 500;
await new Promise((r) => setTimeout(r, wait));
}
throw new Error('out of retries');
}import random, time, requests
RETRYABLE = {429, 500, 503, 50301}
def call(method, path, attempts=4, **kwargs):
for i in range(attempts):
res = requests.request(method, f"https://api.popnow.ai/api/v1{path}", timeout=60, **kwargs)
try:
body = res.json()
except ValueError:
raise RuntimeError(f"HTTP {res.status_code}: {res.text[:200]}")
if body["code"] == 200:
return body["data"]
if body["code"] not in RETRYABLE:
raise RuntimeError(f'{body["code"]} {body["msg"]} ({body.get("request_id")})')
retry_after = res.headers.get("retry-after")
time.sleep(float(retry_after) if retry_after else 2**i + random.random() / 2)
raise RuntimeError("out of retries")createTask を再試行するときは、必ず同じ Idempotency-Key を送ってください。実は成功していたリクエストが二重に実行・課金されるのを防げます。
調査の手順
request_idとcodeを控える。- API コンソールのログで、タスク ID か
request_idからタスクを探す。 - それでも解決しなければ、
request_id、時刻(UTC)、codeを添えてサポートに連絡してください。API キーは絶対に送らないでください。

