◉RORK LABJP
●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SONNET 4.5 — Retires on the Claude API on 11/30, 34 days left. If your app calls it, check the migration target●SDK 58 ISSUE — Early reports include Android widgets not refreshing on a schedule and Stripe linking statically●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SONNET 4.5 — Retires on the Claude API on 11/30, 34 days left. If your app calls it, check the migration target●SDK 58 ISSUE — Early reports include Android widgets not refreshing on a schedule and Stripe linking statically●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…
Articles/Dev Tools
⬡ Dev Tools/2026-10-27Beginner

Claude Sonnet 4.5 Leaves the API on November 30. Find the Model IDs Hard-Coded in Your App First

Claude Sonnet 4.5 is scheduled to retire from the API on November 30, 2026. A small script finds the model IDs written into your app's code and config, so you can replace them and check again.

Claude API14Sonnet 4.5Model RetirementApp Development34Indie Development30Rork603

Deadlines tend to slip past me the same way: I read the notice, think "I'll look at that later," and later never arrives. The Sonnet 4.5 retirement was heading that way for me.

When I opened Anthropic's model deprecations page on October 27, 2026, it listed claude-sonnet-4-5-20250929 as deprecated since September 30, with a retirement date of November 30, 2026 (tentative). The recommended replacement is claude-sonnet-5-5. After the retirement date, requests to the old model fail.

If you added AI features to an app, or called the Claude API yourself from a project you exported from Rork, it is worth checking that date against your own code. Below is the path I followed and actually ran: find the IDs, replace them, check again.

What to know first

You are affected directly only if you wrote the model ID yourself. If you simply pick a model from Rork's menu, the menu already points at Sonnet 5.5, so there is little for you to do.

But an exported project can carry claude-sonnet-4-5-20250929 in an API call, a server function, or a .env file, and any of those stops working after the date. IDs scatter easily. You fix one file, feel relieved, and the same string is still sitting in another.

Step 1: Drop in the audit script

Searching by eye misses things, so I use a small script that walks the project folder. It runs on Node.js with no dependencies. Save it as audit-models.mjs.

// audit-models.mjs — プロジェクト内の Claude モデル ID を洗い出し、廃止予定のものに印を付ける
import { readdirSync, readFileSync, statSync } from "node:fs";
import { join, extname } from "node:path";
 
const ROOT = process.argv[2] ?? ".";
const SKIP_DIRS = new Set(["node_modules", ".git", ".expo", "ios", "android", "dist", "build"]);
const EXTS = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".json", ".env", ".toml", ".yml", ".yaml", ".md"]);
 
// 公式の廃止ページ(platform.claude.com/docs/en/resources/model-deprecations)で確認した値。実行前に見直すこと。
const RETIRING = {
  "claude-sonnet-4-5-20250929": { on: "2026-11-30", to: "claude-sonnet-5-5" },
};
// 別名(エイリアス)。固定のスナップショットではなく、先で指す先が変わりうるもの
const ALIAS = /^claude-sonnet-4-5$/;
 
// claude-<名前>-<数字>(-<数字>)(-<8桁日付>) の形を拾う
const MODEL_RE = /claude-(?:[a-z]+-)?(?:[a-z]+-)?\d+(?:-\d+)?(?:-\d{8})?/g;
 
const hits = [];
function walk(dir) {
  for (const name of readdirSync(dir)) {
    const p = join(dir, name);
    const st = statSync(p);
    if (st.isDirectory()) { if (!SKIP_DIRS.has(name)) walk(p); continue; }
    if (!EXTS.has(extname(name)) && !name.startsWith(".env")) continue;
    readFileSync(p, "utf8").split("\n").forEach((line, i) => {
      for (const m of line.matchAll(MODEL_RE)) hits.push({ file: p, line: i + 1, id: m[0] });
    });
  }
}
walk(ROOT);
 
let urgent = 0;
for (const h of hits) {
  const r = RETIRING[h.id];
  const tag = r ? `要置換 → ${r.to}(${r.on} 終了)` : ALIAS.test(h.id) ? "別名: 指す先を公式で確認" : "対象外";
  if (r) urgent++;
  console.log(`${h.file}:${h.line}\t${h.id}\t${tag}`);
}
console.log(`\n合計 ${hits.length} 件 / 要置換 ${urgent} 件`);
process.exit(urgent > 0 ? 1 : 0);

Run it like this:

node audit-models.mjs ./my-app

If even one line needs replacing, the exit code is 1. That value becomes your pass/fail signal later.

Step 2: What it found in a test folder

Before pointing it at a real project, I tried it on a throwaway folder with four files: .env, src/ai.ts for the app side, supabase/functions/chat/index.ts for a server function, and src/notes.ts containing only a comment.

LocationID foundVerdict
.env, line 1claude-sonnet-4-5-20250929Replace
src/ai.ts, line 1claude-sonnet-4-5-20250929Replace
src/ai.ts, line 2claude-haiku-4-5-20251001Not affected
src/notes.ts, line 1 (in a comment)claude-sonnet-4-5Alias: check what it points to
supabase/functions/chat/index.tsclaude-sonnet-4-5-20250929Replace

Six hits in total, three needing replacement. What I did not expect was that the same ID lived in three separate layers: config, app, and server function. I built that folder myself, but as an indie developer I know how it happens in real apps: every time you add a feature, you copy the string along.

Step 3: Replace, then run it again

The replacement target is claude-sonnet-5-5, taken from the migration example on the official page. The command only touches the exact old ID, so other models stay as they are.

grep -rl "claude-sonnet-4-5-20250929" ./my-app --exclude-dir=node_modules --exclude-dir=.git \
  | xargs sed -i 's/claude-sonnet-4-5-20250929/claude-sonnet-5-5/g'
node audit-models.mjs ./my-app
echo "exit=$?"

In the test folder the second run printed "6 hits / 0 to replace" and the exit code dropped to 0. On macOS, sed -i needs an empty string after it (sed -i '' 's/…/…/g').

Pitfalls: replacing is not the end

The script only tells you that the string is gone. Whether your app still behaves well on the new model is a separate check. Response length, phrasing, and output format can shift. Anything that asks for JSON, or branches on the first words of a reply, is worth running by hand.

I also left date-less aliases such as claude-sonnet-4-5 out of the verdict. What an alias resolves to has to be confirmed in the official docs, and I could not state it with certainty, so the script just says it cannot decide.

Finally, the script reads only source and config files. It cannot see values typed into an admin console, an environment variable set directly in Supabase or Cloudflare, or another service's settings. After fixing the code, open those places yourself once.

For next time: keep the model ID in one place

So the next retirement notice does not catch you off guard, here is a shape worth adopting while you are already editing. I did not run this one in the test folder, so take it as a sketch of the idea.

// src/config/models.ts — the model ID lives here and nowhere else
export const CHAT_MODEL = process.env.CLAUDE_CHAT_MODEL ?? "claude-sonnet-5-5";

Callers use `import { CHAT_MODEL } from "./config/models"`. With that in place, the next retirement means editing one line.

Next step

Run node audit-models.mjs once on your project and look only at the count. If it is zero, you are done for this deadline.

For my part, this exercise reminded me that the model ID belonged in a single constant from the start, and I plan to begin there the next time I add a feature. Retirement dates can move, so it is worth reopening the official deprecations page once more in early November.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

◉ AI Models2026-10-25
Is Your Rork App Still Calling Sonnet 4.5? Finding Out Before November 30
Claude Sonnet 4.5 is scheduled to retire from the API on November 30, 2026. A small script to find leftover model IDs in your app, and the order to fix them in depending on where they live.
⟐ Business2026-04-22
Rork: From Launch to Your First $1,000 — ASO, Pricing, and Launch Marketing Playbook
Shipping a Rork app to the App Store is not the same as earning from it. A step-by-step playbook for ASO, pricing, and launch marketing that gets you to your first $1,000 in revenue.
⬡ Dev Tools2026-10-27
Your EAS Update Opens in Expo Go on iPhone but Stops on Android with "Failed to download remote update". The 403 You Get Even When Signed In
An EAS Update that opens in Expo Go on iOS but stops on Android (SDK 57) with Failed to download remote update. The cause is a sign-in token saved in one place and read from another, and the fix sits on the SDK 58 side. The order to check things in, and what to run yourself.