Product Docs Pricing Changelog
Start free Sign in
Docs / SDK reference / Error reference

Error reference

Every failure throws a typed class with .status (HTTP code) and a machine-readable .code. Branch on .code, not on message strings — messages may change, codes won't.

import { AuthError, StorageError, DatabaseError, MissingServiceKeyError } from "@flarelink/client" try { await flarelink.auth.signIn({ email, password }) } catch (err) { if (err instanceof AuthError && err.code === "INVALID_PASSWORD") { // show "wrong password" in the UI } throw err }

All four classes extend FlarelinkError (which extends Error), so err instanceof FlarelinkError catches any of them. .code is string | undefined — a few low-level transport failures arrive without one.

AuthError

Thrown by flarelink.auth.*. The .code is BetterAuth's machine-readable code, surfaced verbatim — so additional codes beyond the common ones below can appear. Handle the ones your UI cares about and re-throw the rest. getMe() is the one exception: it swallows a 401 and returns null instead of throwing.

Code Status Cause & fix
INVALID_PASSWORD401Wrong password on sign-in. Show a generic "email or password is incorrect" (don't reveal which).
USER_NOT_FOUND401 / 404No account for that email. Same generic message as above to avoid account enumeration.
USER_ALREADY_EXISTS422Sign-up with an email that's taken. Offer sign-in or password reset instead.
EMAIL_NOT_VERIFIED403Sign-in blocked because verification is required and the email isn't verified yet. Prompt the user to check their inbox — the Worker auto-resends the link on sign-in attempts.
TOO_MANY_REQUESTS429Rate limit (per-IP) tripped. Back off and retry; surface a "try again in a moment" message.
MISSING_OR_NULL_ORIGIN403The request's Origin isn't in the deployment's trusted origins (or is missing). Add your app's origin in the Auth panel. The most common setup error — see Trusted origins.

StorageError

Thrown by flarelink.storage.*. The codes are emitted by your auth Worker's storage routes (and one is client-side).

Code Status Cause & fix
MISSING_SERVICE_KEY400Client-side: you called flarelink.storage without passing serviceKey to createFlarelink. (Thrown as MissingServiceKeyError.) Construct a server-side client with the key.
INVALID_SERVICE_KEY401The key doesn't match the deployment's stored hash. Rotated it recently? Update your env. Mistyped? Re-copy from the dashboard.
SERVICE_KEY_NOT_PROVISIONED412No service key has been minted for this (legacy) deployment yet. Hit Redeploy on the Auth panel — it mints one and reveals it once.
R2_NOT_CONFIGURED412R2 credentials aren't set for the project. Attach R2 / generate or paste a keypair on the Files page. See Rotating R2 credentials.

DatabaseError

Thrown by flarelink.from(…) and flarelink.sql\`…\`. The first group is caught client-side before the request is sent (programmer error); the second is propagated from your auth Worker's D1 routes.

Client-side (validation, status 400)

CodeCause & fix
INVALID_IDENTIFIERA table or column name that isn't /^[A-Za-z_][A-Za-z0-9_]*$/. Don't interpolate user input as an identifier.
UNSUPPORTED_FILTERA .where() value that isn't equality (e.g. an array or object). Use flarelink.sql\`…\` for IN, ranges, OR.
INVALID_LIMIT / INVALID_OFFSETA non-integer or negative .limit() / .offset(). Pass a non-negative integer.
EMPTY_INSERT / EMPTY_ROW.insert() with no rows, or a row with no columns. Provide at least one column.
EMPTY_PATCH.update({}) with no columns to set. Provide at least one.

Server-side (propagated from D1)

CodeStatusCause & fix
INVALID_SQL400Empty or malformed SQL reached the Worker. Check your flarelink.sql\`…\` template.
D1_QUERY_FAILED400 / 500D1 rejected the query (syntax, missing table/column, constraint violation). The underlying D1 message is included — read it.
INVALID_BATCH400A batch request was malformed (the internal /api/db/batch route). Generally not hit through the public SDK.
D1_BATCH_FAILED400 / 500A batch hit a D1 error; the whole batch rolled back atomically.
INVALID_SERVICE_KEY / SERVICE_KEY_NOT_PROVISIONED401 / 412Same as in StorageError — DB routes require the service key too.

MissingServiceKeyError

A dedicated subclass thrown immediately (code MISSING_SERVICE_KEY, status 400) when you call flarelink.storage or flarelink.from(…) / flarelink.sql\`…\` without passing serviceKey to createFlarelink. It's a fail-fast guard against accidentally shipping a server-only call to the browser. Construct a separate server-side client with the key — never expose the key client-side.

Something unclear or missing? [email protected] llms-full.txt ↗