Menu

Limits and errors

What bounds a request, what a visitor sees when something fails, and what your code can catch. Operator-side defaults and the files that define them are in default policies. Numbers below are the code's defaults; an administrator's site policy can only lower the per-execution limits, and a manifest can only lower the timeout and memory (Manifest).

Per-execution limits

ExecutionLimits::default() in crates/core/src/execution.rs:

Limit Default What happens when exceeded
Wall time 1,000 ms Execution is terminated: HTTP 504. No catch or finally runs.
JS memory 32 MiB HTTP 500.
Request body 1 MiB Edge answers 413 before your code runs.
Response body 4 MiB HTTP 500 (response too large).
Host calls 64 The next call rejects with QUOTA_EXCEEDED.
Database rows 100,000 A call rejects with QUOTA_EXCEEDED.
Egress bytes 8 MiB A call rejects with QUOTA_EXCEEDED.
Mail messages 10 A call rejects with QUOTA_EXCEEDED.
Storage write bytes 16 MiB A call rejects with QUOTA_EXCEEDED.
Host buffer bytes 16 MiB A call rejects with QUOTA_EXCEEDED.
Password hash/verify calls 2 (fixed) quota_exceeded from microhost/auth.
Console output 64 KiB Later lines are dropped silently.
getRandomValues 65,536 bytes per call RangeError.
Modules 256 modules, 8 MiB of source The import fails.

Notes:

Per-call limits

Call Limit
Host-call timeouts (a slow call rejects with HOST_UNAVAILABLE; the script keeps running) SHA-256 1 s, env 1 s, admin verify 1 s, auth and storage 2 s, database query or execute 5 s, database transaction 10 s, mail 10 s, fetch 15 s.
Database broker SQL text 64 KiB, 999 bound parameters, a query or execute at most 2 s, a transaction at most 5 s and 256 statements, 4 concurrent connections per site, 16 MiB per string, blob or row. The shared transport accepts at most 100 statements per transaction and 1 MiB of request payload.
Storage Key 1,024 bytes; list returns at most 1,000 names; site quota 256 MiB and 10,000 objects by default.
fetch Port 443, exact allowed hosts, at most 3 redirects, request and response bodies 1 MiB each (production composition), 5 s connect, 30 s total.
Mail By default 10 recipients and 256 KiB per message; outbox 100 queued messages and 5 MiB per site.
Wire envelopes One host call, request or reply, is at most 16 MiB encoded (the Linux worker frame cap). Binary data is carried as U+0000..U+00FF strings, so escaping can make an encoded payload several times the raw size. The shared host-call envelope limits a BLOB value to 4 MiB and a storage payload to (16 MiB - 4 KiB) / 6 bytes (about 2.7 MiB); engine transports that predate the shared envelope may apply different limits, so keep single objects well below 2 MiB.
Sessions User id 256 bytes, data 1,024 bytes of JSON, lifetime 1 to 2,592,000 s, Cookie header read up to 4,096 bytes, Set-Cookie value at most 4,096 bytes.
Auth Password 1,024 bytes, 4 concurrent hashes platform-wide, 2 s deadline.

Platform request limits

Defaults: headers 16 KiB, request target (path plus query) 8 KiB, request body 1 MiB read within 30 s, header read timeout 10 s, 60 requests per 60 s per client IP.

Build and deploy limits

Item Limit
Manifest 64 KiB, 256 routes, 32 external hosts, 64 workspace database names
microhost.config.js build 2 s, 50,000,000 fuel, 32 MiB, 64 KiB output, 1,000 files listed, 1 MiB reads
Migrations 128 files, 256 KiB each, 2 MiB total, 15 s
Static files (public/) Streamed from disk in 256 KiB chunks, so a file of any size that fits the 200 MiB extracted limit is served with constant memory. Range (one range), HEAD, ETag and 304 are supported.
External files (public/ files the platform moved to an external store) Same URL, headers, Range, ETag (the quoted SHA-256) and 304 as local files. At most 8 open reads from the store per site and 32 on the platform at once; reads served from the platform's cache do not count. Store timeouts: connect 5 s, first byte 10 s, idle 30 s. See External storage.
ZIP Admin API upload 32 MiB by default; extracted 200 MiB, 10,000 files, depth 16, ratio 100, 60 s
Release retention limits.keep_releases, default 5 (2 to 100); the active release is always kept
Admin extensions 4 per site, 8 pages, 32 requests, 24 elements per page, 32 KiB input, 256 KiB response, 5 s

What visitors see

Visitors only ever see generic texts. Details go to the operator log and the site log (the console output of your handler, capped at 64 KiB per execution).

Edge

Condition Status
Malformed path or Host 400
Unknown host, hidden path, /_admin, missing file, no script, refused file 404 (generic body)
Static file with a method other than GET or HEAD; route with a method that is not allowed 405 with Allow
Body read timeout 408
Body above the limit 413
Request target above 8 KiB 414
Headers above the limit 431
Client-IP or site request budget exhausted 429
Header read timeout Connection closed
Internal failure while serving a file 500
A file that lives in external storage, and the store cannot be reached, the object is gone, or the store's concurrent-read cap is reached 502 Bad Gateway (generic body, nothing about the store)

An external file never falls back to another file or to a stale copy: it is served from the platform's cache or from the store, or it is a 502. Local files of the same site are not affected. A HEAD or a conditional request (If-None-Match) for an external file is answered from the platform database, so it still works while the store is down.

For a known site, these answers (except the malformed, 414, 431 and per-IP 429 ones) can be replaced by your own pages: see Error pages.

Execution

Condition Status and text
Uncaught exception or rejected promise, a thrown sdk_module_disabled, a dynamic import, memory limit, response too large, engine failure 500 Internal Server Error
Handler resolved to a non-Response, invalid status, illegal header name or value (CR or LF), Set-Cookie over 4,096 bytes 502 Bad Gateway
Timeout 504 Gateway Timeout
Capability refused at load (import outside the release, or a public/ file) 403 Forbidden
Dispatch not available (serve --dev) 501 Not Implemented

A handler that catches a coded host error can answer however it likes; only uncaught failures produce these generic pages.

Error codes

Your code sees three families of codes. Always branch on error.code, never on the message (messages are generic and carry no paths or SQL).

Host-call errors (ctx.db, ctx.storage, ctx.env, ctx.mail, fetch, microhost/session): the thrown Error has an uppercase code.

Code Class Meaning
CAPABILITY_DENIED CapabilityError The grant is absent, revoked, or the destination or name is not allowed. Checked on every call.
QUOTA_EXCEEDED QuotaError A budget above is exhausted.
INVALID_INPUT TypeError The call received invalid arguments (also thrown for client-side argument checks).
HOST_UNAVAILABLE HostError The backing service is unavailable or the call timed out.
HOST_INTERNAL HostError An internal host failure.
invalid_admin_request AdminRequestError verifyAdminRequest failed.

SDK module errors use lowercase snake_case codes:

Code Module Meaning
db_use_sql_template, db_multiple_rows, db_duplicate_column, db_no_such_column, db_where_required, db_invalid_direction microhost/db See Database SDK.
capability_denied microhost/db, microhost/session import ctx.db is absent or revoked at the call; or the import was refused.
sdk_module_disabled any module import The module is not requested or an administrator disabled it.
invalid_input, quota_exceeded, host_unavailable, host_internal, capability_denied microhost/auth Thrown as Error with name HostError; see Auth and sessions.

microhost/session rejects bad arguments with INVALID_INPUT (uppercase, TypeError) and passes broker errors through with their uppercase codes.

Admin API codes of external storage (deploys and the storage actions; see External storage):

Code Status Meaning
release_assets_unavailable 409 A deploy, publish or rollback refused to activate a release because an object it needs is missing from the store, has another size, or the store could not be reached. The previous release stays live. Run verify, fix the store, deploy again.
operations_unavailable 503 verify and reconcile are not available on this server (development mode, or no secret vault).
store_in_use 409 The store's location cannot change, or the store cannot be removed, while files reference it.

Revocation. A grant revoked before a call's policy check makes that call fail with capability_denied or CAPABILITY_DENIED, even in the middle of an execution (for example between two pages of a query). There is no grace period; a call already past its check may finish. If the platform cannot read the current policy it fails closed with the same code.

Job limits

Scheduled and background jobs run with their own limits: 30 seconds wall clock by default (10 minutes at most, timeoutMs), 64 MiB memory, 1,000 host calls, 1,000,000 database rows and 32 MiB outbound. They run in a separate capacity pool (2 at once on the platform, 1 per website). The run states and error codes are listed in Scheduled jobs.

Debugging checklist

Symptom Check
501 on a script endpoint You are on serve --dev, which serves static files only.
404 Host mapping, active release, route and script paths; hidden path (a dot segment); a /_admin path.
405 Route method list; handler checks; a static file or exact route shadowing your path.
403 A refused import (outside the release, or public/).
429 Per-IP or per-site request budget.
500 Uncaught exception, sdk_module_disabled, memory, response over 4 MiB, dynamic import. Read the site log.
502 The handler did not return a Response, or a header or status is invalid. For a static file: it lives in external storage and the store failed (ask the operator to run verify).
504 Wall time exceeded (default 1 s); hashing, large queries or slow fetch calls add up.
ctx.db is undefined Not requested in the manifest, or not granted.
capability_denied from microhost/db ctx.db absent or revoked.
Import fails Relative .js path, private namespace, module limits, sdk list.