Supabase Edge Function BOOT_ERROR: Fix "Failed to Bootstrap"
Supabase Edge Function returns {"code":"BOOT_ERROR"}? Here is how to tell apart the four real causes — bad imports, Deno syntax, CLI version, wrong entrypoint.
A Supabase Edge Function that returns:
{"code":"BOOT_ERROR","message":"Worker failed to boot (please check logs)"}or a log line reading worker boot error: failed to bootstrap runtime: failed to determine entrypoint is failing before a single line of your handler runs. This isn't a runtime exception you can try/catch — the Deno worker never finished loading your function's module graph. That distinction matters because it rules out most application-level debugging and points you at four specific causes.
Cause 1 — an import outside supabase/functions/#
The most common trigger: your function imports a local file that lives outside its own directory tree — for example a shared utils.ts sitting at your project root instead of inside supabase/functions/_shared/. Locally, this is a known limitation of the Edge Runtime's module resolution; in production it fails to build the dependency graph entirely.
Fix: move any shared code into supabase/functions/_shared/ and import with a relative path from there. Don't reach outside the functions/ directory, even for genuinely shared utilities.
Cause 2 — a syntax error or unsupported import Deno rejects#
If the boot log names a specific file and mentions "Unexpected reserved word" or a similar parse error, the module itself has a syntax issue — often from code written for Node.js and pasted in unmodified. Edge Functions run on Deno, not Node.js: require(), Node-only built-ins (fs, path without the node: prefix), and CommonJS-style exports don't resolve the way they do in a Next.js API route.
Fix: run the function through deno check locally before deploying, and confirm every import either uses an npm: or jsr: specifier (Deno's supported ways to pull Node/npm packages) or a Deno-native ESM import — not a bare Node import.
Cause 3 — a Supabase CLI version regression (Windows-specific)#
If imports that worked yesterday suddenly BOOT_ERROR after a routine npm update or CLI upgrade, check your Supabase CLI version — but only if you're on Windows. A confirmed regression (supabase/cli#2862) traces local import failures specifically to CLI v1.187.0+ on Windows, where local file imports resolve incorrectly; the same CLI version works fine on macOS and Linux. If you're not on Windows, skip this cause and keep looking.
Fix (Windows only): pin the CLI to a known-good version (npm install supabase@1.186.3 --save-dev or the pinned version your team last verified) until the regression is patched, and track supabase/cli#2862 before upgrading again.
Cause 4 — a supabase-js version mismatch inside the function#
If your function itself imports @supabase/supabase-js at "latest" rather than a pinned version, a new release can introduce a boot-time incompatibility with the Edge Runtime's Deno version. Pinning to a specific, verified version (for example @2.49.8 or whatever your team has last confirmed working) removes this as a variable.
How to actually see the real error#
BOOT_ERROR in the client response is deliberately generic — the real cause is always in the logs, not the HTTP response body.
supabase functions deploy my-function --debugand separately, check Dashboard → Edge Functions → Logs for the exact stack trace and shutdown reason before touching any code. Guessing from the generic BOOT_ERROR message alone wastes more time than reading the log line above it.
Cause 5 — a relative import missing its file extension#
If the shared file already lives inside supabase/functions/_shared/ (Cause 1 is
ruled out) and the code is plain, syntactically valid TypeScript with no Node-only
built-ins (Cause 2 is ruled out too), the next thing to check is whether every
relative import includes its file extension.
Node's module resolver (and the bundler behind most Next.js API routes) will happily
resolve import { helper } from './utils' without an extension, inferring .ts or
.js automatically. Deno's resolver does not do this inference for relative
specifiers — it expects the extension to be there:
// Fails to resolve on Deno — works fine in a Node/Next.js project
import { getUser } from '../_shared/auth'
// Resolves correctly
import { getUser } from '../_shared/auth.ts'Because this is a resolution failure rather than a parse error, the symptom is the same generic boot error / "failed to determine entrypoint" this page opened with — Deno never gets far enough into loading the module graph to report which specific import was the problem in a way that's easy to spot at a glance. Code that was copy-pasted from a Next.js API route or a shared package that relies on extension-less imports is the most common source of this, since it's syntactically identical TypeScript that simply resolves differently on the two runtimes.
Fix: add the explicit extension (.ts, or .js if the shared file is plain
JavaScript) to every relative import inside supabase/functions/, including inside
files under _shared/ that import from each other. This is unrelated to the
npm:/jsr: specifier rule from Cause 2 — those already require full resolution
paths — it only affects your own relative, same-project files. Projects that also
run Deno-targeted code through a shared deno.json for lint/format config (the same
kind of setup covered for the broader Next.js + Supabase deployment pipeline in
Supabase Edge Functions in Next.js: Setup to Cron (2026))
can catch this class of error before deploying by running deno check against the
function's entrypoint, the same command already recommended for Cause 2 above.
Cause 6 — a bare specifier with no import map entry#
Cause 2 covers Node-style require() and CommonJS syntax. A narrower, easier-to-miss
variant of the same underlying problem is a bare specifier written in otherwise
valid ESM syntax — import { z } from 'zod' with no npm: prefix and no matching
entry anywhere that tells Deno where zod actually resolves to.
Node resolves a bare specifier like 'zod' by walking up node_modules
automatically. Deno has no equivalent automatic lookup for arbitrary bare names: it
only resolves a bare specifier if it appears as a key in an import map — the
imports block of a deno.json (or import_map.json) file in scope for that
function — or if it's rewritten to use Deno's own npm:/jsr: specifier scheme
instead. Without one of those two things in place, the specifier fails to resolve
during module-graph construction, before your handler code runs, which again
surfaces as the same generic boot error this page opened with rather than a
descriptive "package not found" message.
Supabase's own dependency-management docs confirm this: npm: specifiers and a function-scoped deno.json import map are the two supported ways to resolve a bare package name, and deno.json is the current recommendation over the legacy import_map.json. Two independent fixes exist, and either is sufficient on its own:
// deno.json — import map entry that lets a bare specifier resolve
{
"imports": {
"zod": "npm:zod@^3"
}
}// or skip the import map and use the npm: specifier directly at the call site
import { z } from 'npm:zod@^3'If a function was copy-pasted from another Edge Function that has its own
deno.json sitting one level up, double check that the map actually applies to the
function's own directory — Deno resolves import maps relative to their location,
the same directory-scoping rule already covered under Cause 1 for shared code, so a
map that lives outside the function's own folder may simply not be picked up at
deploy time even though it looks correct when read locally. Once the function boots
cleanly, the next place an npm-sourced dependency commonly causes trouble is reading
server-only credentials inside the function body — covered in
Does Supabase service_role Bypass RLS? Yes — Use It Safely
for the admin-client pattern Edge Functions typically need.
Still stuck? Paste your error.
Paste the error message or stack trace — we check it against every fix and tool on the site.
Related fixes & guides
- Fix: Multiple GoTrueClient instances detected (Supabase)
- Stop the Supabase getSession() Security Warning
- Supabase "Database Error Saving New User" Trigger Fix
- Next.js + Supabase Background Jobs & Async Patterns
- Complete Guide to Building SaaS with Next.js and Supabase
- Supabase Auth vs Clerk in 2026: The Production Verdict
- Fix "supabaseUrl is required" in Supabase JS
- Supabase Realtime Not Receiving Events: Complete Fix
- Fix Supabase: Invalid Refresh Token Already Used
- Supabase bucket RLS policy for table objects fix

