Logs and debugging

Read Edge Function logs on SupaHost in the Functions tab, over MCP or SSH, understand router error codes like BOOT_ERROR and IDLE_TIMEOUT, and debug failing functions.

Each project with functions keeps one log of everything its functions print and every request they answer. You can read it in the dashboard, from an AI agent over MCP, or over SSH on Business plans. There's no searchable log explorer, and the project Logs tab is still marked coming soon, so this function log is where to look.

Where to read logs

The Logs card

Dashboard → your project → Functions tab → Logs card. It shows the newest 200 entries with Time, Function (with the version that ran), Level and Message. Pick a function from the All functions menu to filter, or click Refresh. The card also refreshes itself every 10 seconds, so you can leave it open while you test.

Every member of the team can read the Logs card.

From an AI agent

The MCP tool get_edge_function_logs returns recent entries, newest first. It takes an optional function_slug and a limit of up to 500 (default 100). A prompt like "Read the last 50 log lines for invoice-reminders and tell me why it returns 500" works well. See MCP tools reference.

Over SSH (Business and Enterprise)

With SSH access set up, print the last 200 lines, or follow new ones:

ssh [email protected]
# then, on the instance:
sudo supahost-logs app-one functions            # last 200 lines
sudo supahost-logs app-one functions --follow   # keep streaming

What gets logged

Type Level What it contains
log info, warn or error Your console.log / console.info, console.warn, console.error output
request info, or error for 5xx One line per request: method, path, status and duration, e.g. POST /invoice-reminders → 200 in 182 ms
boot info or error "Booted in N ms", or the reason a worker failed to start
exception error Uncaught exceptions with the stack trace
shutdown info A worker stopping, with CPU time and memory used

Log structured values to make them easier to read later:

console.log(JSON.stringify({ event: "reminder_sent", invoiceId: invoice.id, ms: Date.now() - t0 }));
console.error("Resend rejected the email", res.status, await res.text());

Don't log secrets, access tokens or whole request headers.

How long logs are kept

Retention is by size, not time. The log file is capped at 8 MB; when it passes that, it's trimmed to the most recent 2 MB. Readers look at the last 3 MB and return at most 1000 entries. A quiet project keeps days of history; a busy one may keep only minutes.

If you need a lasting record (payments, audit events), write it to a table from the function instead of relying on the log.

Error codes from the router

When something fails outside your code, the router answers with a JSON body and an sb-error-code header:

Status sb-error-code What it means Where to look
404 NOT_FOUND No live function with that name. Check the name and that the status is Live. Returns 404
401 UNAUTHORIZED_NO_AUTH_HEADER Require a JWT is on and no Authorization header was sent. Returns 401
401 UNAUTHORIZED_INVALID_JWT The token isn't a valid, unexpired JWT from this project. Returns 401
503 BOOT_ERROR The worker couldn't start, often an error thrown at the top level of the module or a missing secret read at boot. boot lines in the logs. 503 or 504
546 WORKER_RESOURCE_LIMIT The worker ran out of resources (for example the 150 MB memory limit). The router retries such requests up to 2 times first. shutdown lines show memory used. Memory limit
504 IDLE_TIMEOUT The function didn't start responding within 150 seconds. Timeouts
500 WORKER_ERROR The function threw an error that wasn't caught. exception lines. Returns 500

Responses your own code returns never have sb-error-code, so that header tells you which side produced the error.

A debugging routine

  1. Reproduce it in the dashboard. The Test a function card (owner only) sends a real request as the anon key or as service_role and shows status, duration, any sb-error-code and up to 64 KB of the body.
  2. Read the logs for that request. Filter the Logs card to the function. Look for exception or boot errors just before the request line.
  3. Add logging around the suspect code, deploy a new version, and repeat. Each deploy takes about a minute, and the old version keeps serving until the new one is live.
  4. Check the deploy status. If the row says Deploy failed, your latest code isn't running at all; the build error is under the function's URL.
  5. Check the caller. A 401 with an sb-error-code means the request never reached your code. Compare the token you're sending with Authentication and JWT verification.
  6. Run it locally with supabase functions serve if you need a debugger or faster iteration (see Local development with the Supabase CLI).

Updated 11 November 2026 · View as Markdown · Something wrong or missing? Tell us