夕方にデプロイした自動投稿エージェントから、突然「このモデルは現在利用できません」というエラーが返ってきて困ったことはないでしょうか。リトライしても変わらず、しばらく経つと直り、また数時間後に同じことが起きる。私自身、2014年からアプリ事業をやってきた個人開発者として、6サイトのコンテンツ自動投稿パイプラインを Claude API で動かしていて、新モデルがリリースされた直後の週末によくこの症状に遭遇します。
このエラーは 529 Overloaded や 429 Rate Limit とは性質が異なります。サーバ側の混雑ではなく、自分が指定したモデル ID そのものに対する一時的な利用不可状態 が原因です。リトライしてもモデル ID が変わらなければ永遠に弾かれ続けるので、対処は「待つ」ではなく「切り替える」設計になります。
ここでは、半年間 Claude API を本番運用してきて把握した発生条件と、私のパイプラインで稼働しているフォールバック実装の中身を整理します。
このエラーが出る5つの典型パターン
ログとサポートチケットの履歴を半年分振り返ると、発生条件はほぼ5つに収まります。
- 新モデルのリリース直後数時間: たとえば Claude Sonnet 4.6 がリリースされた当日、リージョンごとの段階展開中に古い SDK が新 ID を指定すると不安定になりました
- 古いモデル ID の指定(廃止予告期間中): 公式に廃止が予告されたモデルは、deprecation 日付の前から一時的に「利用不可」が断続的に返ることがあります
- 特定リージョンのみで未配信のモデルを指定: AWS Bedrock 経由・Vertex AI 経由などでは、リージョンによって配信モデルが異なります。Anthropic 直 API では起きにくいですが、マルチクラウド構成だと頻発します
- ベータ機能フラグの組み合わせが無効: extended thinking + parallel tool_use + computer use のような複数機能を同時に有効化すると、組み合わせとして配信されていない時間帯にエラーが返ります
- アカウントレベルの一時的なクオータ違反: Tier 1 のアカウントが Tier 2 限定モデルを指定したときなど、権限ベースでの拒否がこのメッセージで返ることがあります
私の手元の集計では、発生率はだいたい 1番目 40% / 2番目 15% / 3番目 5% / 4番目 25% / 5番目 15% でした。1番目と4番目を合わせて 65% を占めるので、対処の最優先はこの2つです。
モデル ID の動的フォールバック表
最も効くのが「指定モデル ID を切り替えるフォールバック表」を持つことです。私のパイプラインでは、各タスクごとに「優先モデル」と「フォールバック先 1〜3」を定義しています。
type ModelTier = "frontier" | "balanced" | "fast";
interface ModelFallbackChain {
primary: string;
fallbacks: string[];
}
const FALLBACK_CHAINS: Record<ModelTier, ModelFallbackChain> = {
frontier: {
primary: "claude-opus-4-6",
fallbacks: ["claude-sonnet-4-6", "claude-sonnet-4-5"],
},
balanced: {
primary: "claude-sonnet-4-6",
fallbacks: ["claude-sonnet-4-5", "claude-haiku-4-5-20251001"],
},
fast: {
primary: "claude-haiku-4-5-20251001",
fallbacks: ["claude-haiku-4-5", "claude-haiku-4"],
},
};タスクごとに「frontier 級が欲しいけど落ちるくらいなら balanced で続行する」「fast 級でいい場面で frontier を使わない」といった切り替えを宣言的に持つようにしました。これだけで、新モデル展開時の止まる時間が体感で 90% 短縮されました。具体的には、Claude Sonnet 4.6 リリース直後の週末、私の自動投稿パイプラインは平均 3 時間停止していたのが、フォールバック実装後は平均 8 分以内に復旧するようになりました。
エラー判別とフォールバック実行ロジック
このエラーは HTTP ステータスとしては 400 系で返ってきますが、エラーメッセージで判別します。SDK のレスポンスに含まれる error.type と error.message を見て分岐します。
import Anthropic from "@anthropic-ai/sdk";
async function invokeWithFallback(
client: Anthropic,
tier: ModelTier,
buildRequest: (modelId: string) => Anthropic.Messages.MessageCreateParams
): Promise<Anthropic.Messages.Message> {
const chain = FALLBACK_CHAINS[tier];
const candidates = [chain.primary, ...chain.fallbacks];
let lastError: unknown;
for (const modelId of candidates) {
try {
const req = buildRequest(modelId);
return await client.messages.create(req);
} catch (err) {
if (isModelUnavailable(err)) {
console.warn(`model ${modelId} unavailable, trying next`);
lastError = err;
continue;
}
// 別種のエラーは即座に投げ返す。フォールバックの対象ではない
throw err;
}
}
throw lastError;
}
function isModelUnavailable(err: unknown): boolean {
if (!err || typeof err !== "object") return false;
const e = err as { status?: number; error?: { type?: string; message?: string } };
if (e.status !== 400 && e.status !== 404) return false;
const msg = e.error?.message?.toLowerCase() ?? "";
return (
msg.includes("currently unavailable") ||
msg.includes("model is not available") ||
msg.includes("model_not_available") ||
e.error?.type === "model_not_found_error"
);
}ここでのコツは、フォールバックの対象を エラーメッセージで限定する ことです。レート制限(429)や Overloaded(529)まで一緒にフォールバックしてしまうと、混雑状況がフォールバック先に伝播するだけで実害が増えます。判別関数は厳密に書いてください。
ベータ機能フラグの組み合わせを意識する
4番目の原因がやっかいなのは、開発時には動いていた組み合わせが、ある時間帯だけ動かなくなるためです。たとえば私が運営している Lacrima と Mystery のブログ自動投稿エージェントは、extended thinking と parallel tool_use を同時に使う構成になっています。Claude Sonnet 4.6 では問題なく動くのに、4.5 にフォールバックすると「extended thinking + parallel tool_use の組み合わせはこのモデルでは未対応」と返ってくる時間帯があります。
対策は、フォールバック先ごとに 有効化するベータ機能の組み合わせ を別に持つことです。
interface ModelCapabilities {
modelId: string;
extendedThinking: boolean;
parallelToolUse: boolean;
computerUse: boolean;
// ... 他の機能フラグ
}
const CAPABILITY_MATRIX: Record<string, ModelCapabilities> = {
"claude-opus-4-6": {
modelId: "claude-opus-4-6",
extendedThinking: true,
parallelToolUse: true,
computerUse: true,
},
"claude-sonnet-4-6": {
modelId: "claude-sonnet-4-6",
extendedThinking: true,
parallelToolUse: true,
computerUse: false,
},
"claude-sonnet-4-5": {
modelId: "claude-sonnet-4-5",
extendedThinking: true,
parallelToolUse: true,
computerUse: false,
},
"claude-haiku-4-5-20251001": {
modelId: "claude-haiku-4-5-20251001",
extendedThinking: false,
parallelToolUse: true,
computerUse: false,
},
};
function buildRequestForModel(
modelId: string,
basePrompt: string,
tools: Anthropic.Messages.Tool[]
): Anthropic.Messages.MessageCreateParams {
const caps = CAPABILITY_MATRIX[modelId];
return {
model: modelId,
max_tokens: 4096,
messages: [{ role: "user", content: basePrompt }],
tools,
...(caps.extendedThinking ? { thinking: { type: "enabled", budget_tokens: 16384 } } : {}),
};
}「機能を全部 ON にしたいけど落ちるくらいなら段階的に OFF にする」発想で書いてあります。私のパイプラインでは、フォールバックチェーンの後段ほど機能フラグが少なくなる設計になっており、最後の砦のモデルは extended thinking を切ってでも応答が返ってくることを優先しています。
アカウントレベルのクオータ違反は別ログに分ける
5番目の原因(権限ベースの拒否)は、技術的フォールバックでは解決しません。アカウントの Tier 設定を見直すか、別の API キーに切り替える必要があります。これを混ぜると本番の運用ログがノイズだらけになるので、「フォールバック可能」と「サポート問い合わせが必要」を最初に判別 したほうがよいです。
function isModelUnavailable(err: unknown): boolean {
// 同上
}
function isAccountTierViolation(err: unknown): boolean {
if (!err || typeof err !== "object") return false;
const e = err as { error?: { message?: string } };
const msg = e.error?.message?.toLowerCase() ?? "";
return (
msg.includes("not authorized") ||
msg.includes("tier") ||
msg.includes("upgrade your account")
);
}私のパイプラインでは、Tier 違反は Slack 通知で即座にアラートを上げる経路に分けています。フォールバックループに入れても解消しないからです。
切り替えコストを観測する仕組み
フォールバック実装の運用で大事なのが「どれくらい代替モデルに落ちているか」を観測する仕組みです。私は次のような形でログを出しています。
interface ModelInvocationLog {
timestamp: string;
intendedModel: string;
actualModel: string;
fallbackDepth: number; // 0 = primary, 1 = first fallback...
taskType: string;
outcome: "success" | "all_failed";
}
async function loggedInvoke(/* ... */) {
// invokeWithFallback の中で、最終的にどのモデルで成功したかをログに残す
const log: ModelInvocationLog = { /* ... */ };
await appendInvocationLog(log);
}このログを週次で集計し、fallbackDepth >= 1 の割合が 5% を超えたら設定を見直すルールにしました。だいたい新モデル展開直後の1〜2週間だけ 10〜15% に跳ね、その後 2% 前後に落ち着くというパターンです。
開発時にこのエラーを再現する
最後に開発時の Tips を一つ。このエラーは本番でしか出ないので動作検証が難しいのですが、model フィールドに 存在しない ID(例: claude-opus-99-xxx)を渡すと、ほぼ同等のレスポンスが返ってきます。フォールバック実装の単体テストはこれで通せます。
私の運用では、CI のたびにフォールバックチェーンの全段がエラーレスポンスを受けても正しく次に進むかを検証する E2E テストを回しています。本番でモデルが落ちた瞬間に「テストしてなかった」を経験して以来の習慣です。
このエラーに遭遇したら、まずモデル ID の指定とベータ機能フラグの組み合わせを疑い、しばらく直らないようなら段階的なフォールバック設計に投資する価値があります。私自身、半年運用してこの仕組みのおかげで深夜の緊急対応が大幅に減りました。同じ症状に悩まされている方の参考になれば幸いです。