Error codes
Every status code walkindb can return, when you'll see it, and what to do about it.
All error responses use the same JSON shape:
{"error": "short human-readable message"}
400 Bad Request
invalid json
The request body is not valid JSON. Most commonly caused by embedded newlines inside a JSON string literal — JSON does not allow literal newlines inside "..." strings, only escaped \n.
# WRONG — raw newline inside the JSON string -d '{"sql":"CREATE TABLE t(x); INSERT INTO t VALUES(1)"}' # RIGHT — single line, or escape as \n -d '{"sql":"CREATE TABLE t(x); INSERT INTO t VALUES(1)"}'
missing sql
The JSON body parsed but did not contain a non-empty sql field.
forbidden sql keyword: <keyword>
walkindb's application-level blocklist rejected the query before it reached SQLite. The message names the matched keyword.
Forbidden keywords:
ATTACH/DETACH— walkindb is one-file-per-instance by designload_extension— no dynamic loading, everreadfile,writefile,edit— filesystem scalar functionsfts5_*— internal fts5 admin functions (CREATE VIRTUAL TABLE ... USING fts5(...)still works)sqlite_dbpage,zipfile,unzip
The match is case-insensitive and the blocklist strips SQL comments before matching, so /* skip */ ATTACH still trips.
invalid sql: ...
SQLite returned a syntax or semantic error. The message includes SQLite's original text. Common variants:
invalid sql: near "...": syntax errorinvalid sql: no such table: ...invalid sql: no such column: ...invalid sql: no such function: ...invalid sql: string or blob too big— you hit theLENGTH=1 MBper-value capinvalid sql: expression tree is too large— you hit theEXPR_DEPTH=50capinvalid sql: too many terms in compound SELECT— you hit theCOMPOUND_SELECT=10capinvalid sql: too many attached databases— you tried toATTACH(belt-and-suspenders check afterLIMIT_ATTACHED=0)invalid sql: like or glob pattern too complex— you hit theLIKE_PATTERN_LENGTH=100capinvalid sql: too many levels of trigger recursion
404 Not Found
instance not found
Returned when:
- The
X-Walkin-Sessionheader contains a garbage / tampered token - The token is valid but the instance TTL has already expired (and the sweeper deleted the file)
- The token is valid but signed with a rotated-out HMAC secret (walkindb rotates daily and keeps one previous secret, so tokens survive exactly one rotation cycle)
Walkindb returns the same 404 for all three cases so attackers can't distinguish "wrong token" from "expired" from "no such instance". If you see 404 and you know the token was recent, drop it and let the next call provision a new walk-in.
408 Request Timeout
query exceeded 2s timeout
The query ran for more than 2 seconds wall-clock and was interrupted. Common causes:
- Recursive CTE with no termination condition
- Missing index on a large
JOINorWHEREclause - Pathological
LIKEorGLOBpattern
Interrupted queries don't partially commit — SQLite rolls back.
413 Payload Too Large
sql payload exceeds 8 KB
The request body is larger than 8192 bytes. Split your statements into multiple calls against the same session.
429 Too Many Requests
rate limit exceeded
Your source IP has exceeded 60 requests per minute. Back off and retry after 10 seconds.
new-instance rate limit exceeded
Your source IP has exceeded 10 new walk-in instance creations per minute. This is a separate bucket from the request rate limit. Reuse the session token you already have instead of provisioning fresh instances in a loop.
Retry-After headers. Back off for 10 s and try again; the refill rate for both buckets is smooth.
507 Insufficient Storage
instance storage quota exceeded
The walk-in database has hit the 10 MB max_page_count cap. SQLite itself refuses further writes. There is no way to grow the instance — provision a new one or use a different database entirely.
500 Internal Server Error
internal error
walkindb encountered an unexpected error not covered by any of the cases above. The detail is logged server-side but deliberately not echoed back to avoid leaking internals. If you can reproduce one, please email [email protected] with the exact request — we pay a bounty for security-relevant reproductions.
Handling errors in client code
Python
from walkindb import Client, WalkinDBError db = Client() try: db.execute("SELECT * FROM missing_table") except WalkinDBError as e: if e.status == 400: print("bad sql:", e.error) elif e.status == 404: db.reset_session() # start a new walk-in elif e.status == 429: # wait a bit and retry time.sleep(e.retry_after or 10) elif e.status == 507: # quota full — provision a new walk-in or give up db.reset_session() else: raise
JavaScript / TypeScript
import { Client, WalkinDBError } from "walkindb"; const db = new Client(); try { await db.execute("SELECT * FROM missing_table"); } catch (e) { if (e instanceof WalkinDBError) { if (e.status === 400) console.error("bad sql:", e.error); else if (e.status === 404) db.resetSession(); else if (e.status === 429) await new Promise(r => setTimeout(r, (e.retryAfter ?? 10) * 1000)); else if (e.status === 507) db.resetSession(); else throw e; } }
Also see
- REST API reference
- Security model — why some limits exist
- Python SDK
- JavaScript SDK