# エラーコードと対処方法

> リクエストエラーと文字起こし失敗の違い、エラーの形式、全エラーコードの意味と再試行の判断基準を確認します。

Canonical: https://transcript1.com/ja/docs/errors
Language: ja
Last updated: 2026-11-05

エラーには、APIがリクエストを受け付けなかった場合と、受け付けた後で文字起こしに失敗した場合があります。後者では、文字起こしの`status`が`failed`になります。リクエストが通っただけでは、文字起こしの成功は確定しません。

## エラーレスポンスの形式

`/v1`へのリクエストでエラーが起きると、次の形式のJSONを返します。

```json
{
  "error": {
    "code": "insufficient_minutes",
    "message": "Not enough minutes",
    "retryable": false,
    "action_url": "https://transcript1.com/dashboard/billing",
    "minutes_needed": 20,
    "minutes_remaining": 3
  }
}
```

処理の分岐には`code`を使い、`message`はユーザーへの表示用として扱ってください。`message`の文言は変更することがあります。`retryable`が`true`なら、時間を置いて同じリクエストを再送すると成功する可能性があります。

エラーの種類によっては、`retryable`と並んで次のフィールドも返します。

| フィールド | 返すエラーコード | 内容 |
|---|---|---|
| `action_url` | `insufficient_minutes`、`no_active_plan`、`topup_needs_user` | プランの契約や分数の追加購入ができるページです。 |
| `minutes_needed`、`minutes_remaining` | `insufficient_minutes` | 必要な分数と残りの分数です。必要な分数がまだ不明なら`null`になります。 |
| `reason`、`packs` | `topup_needs_user` | カードに請求しなかった理由と、リクエストしたパック数です。 |
| `supported_platforms` | `unsupported_platform` | 指定できるプラットフォームは`["youtube", "x", "tiktok", "instagram", "facebook", "bluesky", "twitch", "dailymotion", "pinterest", "linkedin", "snapchat"]`です。 |
| `missing_chunks` | `upload_incomplete` | サーバーに届いていないチャンクのインデックスです。 |
| `max_bytes` | `media_too_large` | アップロードできるファイルの最大バイト数です。 |
| `params` | `invalid_request` | ボディやクエリの検証で返します。フィールド名をキー、その問題点を値にしたオブジェクトです。 |

## リクエスト時に返るエラー

| HTTPステータス | `code` | 再試行 | 原因と対処 |
|---|---|---|---|
| 400、422 | `invalid_request` | 不可 | 必要なパラメーターやボディのフィールドがないか、値が不正です。`diarize`と`source: "captions"`、`reuse_recent`と`webhook_url`の併用などが該当します。ボディが正しいJSONでない場合も返します。 |
| 422 | `invalid_url` | 不可 | YouTube、X、TikTok、Instagram、Facebook、Blueskyなどの対応リンクを指定してください。ほかに使えるプラットフォームは[対応リンクと文字起こしの設定](https://transcript1.com/ja/docs/sources-and-options)で確認できます。リンクと`platform`が合わない場合も、このコードを返します。 |
| 422 | `unsupported_platform` | 不可 | `platform`に非対応の値を指定しています。 |
| 422 | `unsupported_media` | 不可 | 送ったファイルの拡張子は使えません。 |
| 401 | `unauthorized` | 不可 | 認証情報がないか、無効・期限切れ・失効済みです。アップロードトークンが無効または期限切れの場合も返します。 |
| 403 | `insufficient_scope` | 不可 | OAuthトークンに`transcriptions:read`または`transcriptions:write`の権限がありません。 |
| 403 | `email_not_verified` | 不可 | メール認証が済んでいません。文字起こしやライブセッションを作成する前に認証してください。 |
| 402 | `insufficient_minutes` | 不可 | 使える分数が0分か、処理に必要な分数に足りません。ライブセッションでは、開始1分分に満たない場合も該当します。[自動追加購入](https://transcript1.com/ja/docs/billing-and-limits#auto-top-up)がオンなら、transcript1は先に追加購入を試みます。`action_url`から分数を購入するか、`POST /v1/topups`やMCPツール`top_up`でエージェントに購入させてください。 |
| 402 | `no_active_plan` | 不可 | 有効な有料プランがない状態で追加購入しようとしました。`POST /v1/topups`とダッシュボードの課金用エンドポイントで返すコードで、文字起こしのエンドポイントでは返しません。 |
| 402 | `topup_needs_user` | `pending`と`in_progress`のみ可 | `POST /v1/topups`でカードに請求しませんでした。理由は`reason`でわかります。`not_allowed`（認証情報に追加購入の許可がない、またはユーザーがチームの管理者でない）、`cap_reached`（エージェント用の月間上限に余裕がない）、`card_declined`、`authentication_required`、`no_card`のいずれかです。ユーザーは`action_url`からパックを購入できます。`pending`（支払いがまだ確定していない）と`in_progress`（別の追加購入が進行中）の場合は、まだ支払いが完了する可能性があります。ユーザーを購入ページへ案内せず、あとで同じ`Idempotency-Key`で再試行してください。 |
| 404 | `not_found` | 不可 | 指定した文字起こしが見つからないか、別のチームに属しています。 |
| 409 | `upload_incomplete` | 不可 | チャンクが不足しています。不足分を送り、完了リクエストを送り直してください。 |
| 409 | `invalid_state` | 不可 | アップロード待ちの状態ではありません。チャンクの送信やアップロードの確定はできません。 |
| 409 | `session_ended` | 不可 | ライブセッションがすでに終了しているため、`POST /v1/live/sessions/:id/token`ではトークンを発行できません。WebSocketの`error`イベントとしても送られます。 |
| 422 | `unsupported_language` | 不可 | ライブセッションの`language`に対応していません。 |
| 422 | `unsupported_translation` | 不可 | ライブセッションの`translate_to`の言語に対応していないか、ライブ翻訳を利用できません。 |
| 409 | `idempotency_conflict` | 不可 | 同じ`Idempotency-Key`を、異なるパラメーターですでに使っています。 |
| 413 | `media_too_large` | 不可 | ファイルがサイズ上限を超えています。[ファイルのアップロード](https://transcript1.com/ja/docs/uploads)で上限を確認してください。 |
| 413 | `invalid_request` | 不可 | JSONボディが1MBを超えています。ファイルのサイズ超過には`media_too_large`を返します。 |
| 429 | `rate_limited` | 可 | 1分あたりのリクエスト数を超えました。`Retry-After`に指定された秒数だけ待ってください。 |
| 429 | `too_many_active_jobs` | 可 | 実行中の文字起こし、または未完了のアップロードが多すぎます。`Retry-After`の秒数だけ待ってください。 |
| 429 | `too_many_live_sessions` | 可 | プランの同時ライブセッション数をすべて使っています。`Retry-After`の秒数(30)だけ待ってください。 |
| 500 | `internal_error` | 可 | transcript1側でエラーが起きました。少し待って再送してください。 |
| 503 | `service_unavailable` | 可 | transcript1を一時的に利用できません。少し待って再送してください。 |
| 503 | `live_capacity` | 可 | ライブの処理容量がすべて使用中です。`Retry-After`の秒数(30)だけ待ってから、セッションを作り直してください。 |
| 503 | `live_unavailable` | 不可 | ライブ文字起こしをいまは利用できません。 |

Bearer認証ではなくログインCookieを使うブラウザーのリクエストは、送信元のオリジンも検証します。別サイトから送ると`403 forbidden_origin`を返します。`Authorization`ヘッダーを付けたAPIリクエストは、この検証の対象外です。

`429`では必ず`Retry-After`ヘッダーを返します。値は、次のリクエストまで待つ秒数です。各上限の値は[料金と制限](https://transcript1.com/ja/docs/billing-and-limits)で確認してください。

## 自動再試行の判断基準

- `retryable`が`true`のときだけ再送します。対象は`rate_limited`、`too_many_active_jobs`、`too_many_live_sessions`、`live_capacity`、`internal_error`、`service_unavailable`と、`reason`が`pending`または`in_progress`の`topup_needs_user`です。`Retry-After`があれば指定どおりに待ち、なければ再送の間隔を徐々に延ばしてください。
- `POST /v1/transcriptions`や`POST /v1/topups`を再試行するときは、同じ`Idempotency-Key`ヘッダーを使ってください。元のリクエストがすでに成功していても、二重課金を防げます。
- それ以外のコードでは、原因を解消してからリクエストを送り直してください。

## ライブ文字起こし

`POST /v1/live/sessions`などのライブ用エンドポイントも、同じエラーレスポンスの形式を使います。上の表のライブ用コードに加えて、`invalid_request`、`unsupported_language`、`insufficient_minutes`、`email_not_verified`も該当します。セッションの作成は冪等ではないため、`too_many_live_sessions`や`live_capacity`のあとに再送すると、新しいセッションが作られます。

セッションができたあとの問題は、HTTPエラーではなく、WebSocketの`error`イベントとクローズコードで届きます。すべてのイベントは[ライブ文字起こし](https://transcript1.com/ja/docs/live#websocket-protocol)を参照してください。

| クローズコード | 意味 |
|---|---|
| `1000` | 正常なクローズです。`session.ended`のあとに送られます。 |
| `1011` | サーバーの予期しないエラーです。新しいトークンで再開してください。 |
| `1012` | サーバーの再起動です。`reconnect`のあとに送られます。新しいトークンで再開してください。 |
| `4001` | トークンが無効、期限切れ、または使用済みです。 |
| `4004` | セッションが見つからないか、すでに終了しています。 |
| `4008` | プロトコル違反です。奇数長または大きすぎる音声フレームを送りました。 |
| `4010` | 同じセッションへの新しい接続に置き換えられました。 |

`balance_exhausted`や`idle_timeout`などの理由で終了したライブセッションはエラーではありません。終了理由つきの`session.ended`が送られ、セッションは保存されます。[終了理由](https://transcript1.com/ja/docs/live#end-reasons)を参照してください。

## 受け付け後に文字起こしが失敗した場合

`status`が`failed`になったら、文字起こしオブジェクトの`error: { "code", "message" }`を確認してください。APIがリクエストへのレスポンスを返した後に、処理が失敗することもあります。ポーリングのレスポンス、または`transcription.failed`の[Webhook](https://transcript1.com/ja/docs/webhooks)で`error`を確認します。 翻訳が失敗した場合は`transcription.translation.failed`のWebhookを送り、文字起こし自体が失敗になることはありません。

| `error.code` | 失敗の原因 | 対処・再実行の目安 |
|---|---|---|
| `media_unavailable` | 動画が見つからないか、利用できない状態です。 | 再試行しません。URLを確認してください。 |
| `media_private` | 非公開の動画です。 | 再試行しません。公開投稿、または公開・限定公開のYouTube動画を指定してください。 |
| `login_required` | 取得にログインが必要です。 | 恒久エラーとして扱い、再試行しません。 |
| `no_audio` | 動画に音声トラックが付いていません。 | 恒久エラーとして扱い、再試行しません。 |
| `age_restricted` | 年齢制限で動画を取得できません。 | 再試行しません。代わりにファイルをアップロードしてください。 |
| `live_stream` | 配信中、またはまだ始まっていないライブ配信です。 | 配信が終わってから再実行してください。 |
| `no_captions` | `source`が`captions`（字幕のみ）で、使える字幕トラックがありません。 | `source: "auto"`または`"stt"`に変えてください。 |
| `media_too_long` | 音声認識で扱える上限の5時間を超えています。 | 再試行しません。音声や動画を分割してください。 |
| `unsupported_media` | ファイルを読み込めないか、音声トラックがありません。 | 再試行しません。対応するファイルを送ってください。 |
| `no_speech` | 発話が検出されませんでした。 | 再試行しません。 |
| `unsupported_language` | 音声で使われている言語に対応していません。 | 再試行しません。`language`を対応する言語コードか`"auto"`に変更してください。 |
| `insufficient_minutes` | 課金の時点で分数が不足していました。自動追加購入がオンの場合も、分数を追加できませんでした。 | 分数を追加購入してから再試行してください。 |
| `fetch_failed` | メディアの取得を複数回試しましたが、取得できませんでした。 | 時間を置いて再実行できます。 |
| `transcription_failed` | 音声認識を複数回試しましたが、処理に失敗しました。 | 時間を置いて再実行できます。 |

文字起こしに失敗した場合やキャンセルした場合は課金しません。すでに差し引いた分数があれば、失敗・キャンセル時に元に戻します。
