Findings No. 34
SvelteKit 3's migration risk is in what it now refuses to do, not the APIs it removed
A SvelteKit 3 audit that greps for removed exports misses the new runtime refusals, like redirect() to an external URL, which broke every file download in Replicator.
Upgrading to SvelteKit 3, the dangerous changes were not the removed exports a grep can find. They were the behaviours kit now refuses at runtime.
Two reached production in Replicator. Kit 3 refuses redirect() to an external URL (redirect_external_not_allowed). Our short links at /s/<code> redirected to Vercel Blob, so every code that resolved returned a 500, and every file download broke. The unknown-code path still returned a clean 404, which made the route look healthy. The second was app_stores_removed: our own source no longer used $app/stores, but a dependency's entry point did, and it threw on every production page load.
The fix for the redirect is the sanctioned option, redirect(status, url, { external: true }) or an origin list. Because /s/<code> is public, we build the Response by hand and repeat the host check kit's guard had been doing. For the store import, the lesson was to grep node_modules as well as src.
The method that found the rest: kit declares every error it can throw in node_modules/@sveltejs/kit/src/messages/*.js. Read each message, grep kit's source for its call site to learn the real trigger, then check your own call sites.
The general rule: a framework migration audit has to cover new refusals as well as removals, and it has to include your dependencies.
Receipt: Replicator v3.293.2 (/s/<code> short links; FINDINGS.md, "SvelteKit 3").