PopNowAPI ドキュメント
リファレンス
本文

エラー

すべての業務コードの意味、対処法、そして再試行する価値のあるエラー。

呼び出しが失敗すると、レスポンスは問題の種類を表す数値(code)と、人が読むための説明文(msg)を返します。分岐には数値を使い、説明文は表示やログに使ってください。

レスポンスの外枠

{ "code": 40201, "msg": "Insufficient balance", "request_id": "req_…" }
  • code は業務コードです。200 が成功で、それ以外は下の表にあります。
  • 失敗時には data フィールドがありません。例外は一部のアセットライブラリのエラーで、data.reason が付きます。
  • HTTP ステータスも正しく設定されます(40201 なら HTTP 402)。どちらか一方で分岐し、混ぜないでください。より具体的な 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 はその理由を英語のまま、内部情報を取り除いて伝えます。

一般的なコード

codeHTTP意味再試行する?
200200 / 202成功—
400400リクエストまたは input が不正。msg が問題点を示しますしない。直してから
40003400アップロードがチケットと合わない(サイズ、種類、内容)しない。チケットを取り直して再アップロード
40004400リクエストは正しいが、モデルが今この設定の組み合わせに対応できないしない。msg に書かれた設定を変える
401401キーがない、認識できない、または無効化済み(詳細)しない
403403許可されていない(権限を参照)しない
404404存在しない、または別のキーのものしない
409409現在の状態と衝突している(再試行の判断)場合による
40901409見積もりの期限切れ、または価格の変更見積もり直す
413413リクエスト本文が大きすぎるしない。インラインではなくアップロードで送る
429429リクエストが多すぎるする。Retry-After のあとで
500500こちら側の障害する。間隔を空けて
503503補助的なサービスが一時的に使えないする。Retry-After のあとで

残高と上限

codeHTTP意味対処
40201402このタスクの確保額に対してクレジットが足りないクレジットを購入してから再送
40202402キーの利用上限に達したAPI コンソールで上限を上げるか、リセットを待つ

権限

codeHTTP意味対処
40301403このキーではこのモデルを呼び出せないキーの許可モデルに追加する
40302403送信元がキーの IP 許可リストにないアドレスを追加するか、制限を外す
40303403この地域ではサービスを提供していない回避できません
40310403アカウントのメールアドレスが未確認登録メールのリンクを開く。確認後すぐキーが使えます

有効なキーで単なる 403 が返る場合は、アカウントが現在 API を使えない状態です。request_id を添えてサポートに連絡してください。

モデルの利用可否

codeHTTP意味再試行する?
50301503このモデルは今タスクを受け付けられないする。時間をおくか別のモデルへ
40004400モデルは動いているが、この設定には対応できないしない。設定を変える

どちらもタスクを作らず、クレジットも確保しません。

タスクの失敗コード

受け付けたあとに失敗したタスクは 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 があればそれに従い、なければ指数バックオフで待ちます。

JavaScript
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');
}
Python
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 を送ってください。実は成功していたリクエストが二重に実行・課金されるのを防げます。

調査の手順

  1. request_id と code を控える。
  2. API コンソールのログで、タスク ID か request_id からタスクを探す。
  3. それでも解決しなければ、request_id、時刻(UTC)、code を添えてサポートに連絡してください。API キーは絶対に送らないでください。

このページの内容