SDK

Error handling

Every SDK error is a LeashError with a machine-readable code, a human message, and (often) an action hint plus a seeAlso doc link.

Error codes

CodeMeaningFix
NO_API_KEYLEASH_API_KEY is missing in server mode.Set LEASH_API_KEY in the env where the SDK runs.
NO_REQUEST_SERVER_CONSTRUCTLeash was constructed in a server environment without a request object.Pass { request: req } to the Leash constructor inside an API route or server handler.
BROWSER_MODE_UNSUPPORTEDLeash was constructed (or a server-only method was called) from the browser. Not supported in 0.4-alpha.Move the call to an API route and construct Leash with { request: req } there.
UNAUTHORIZEDThe leash-auth cookie is missing, invalid, or expired (platform returned 401).Ensure the calling user has a valid session, or use leash dev to mint a local cookie.
INTEGRATION_NOT_ENABLEDThe provider is not connected for this user, or the app is not on the allow-list (platform returned 403).Connect the provider at /dashboard/integrations and confirm the app is allow-listed.
INTEGRATION_ERRORThe upstream provider returned an error. Includes the upstream message.Inspect err.message — most are caller bugs (bad params, missing scopes) or transient upstream issues.
UPGRADE_REQUIREDThe call requires a higher plan (platform returned 402).Upgrade at /dashboard/billing.
NETWORK_ERRORThe SDK could not reach the Leash platform at all.Check connectivity and that LEASH_PLATFORM_URL (if set) points somewhere reachable.

Source of truth: LeashErrorCode in @leash/sdk/leash.

Handle it

app/api/inbox/route.ts
import { Leash, LeashError } from '@leash/sdk/leash'
export async function GET(req: Request) {
const leash = new Leash({ request: req })
try {
const messages = await leash.integrations.gmail.listMessages({ maxResults: 5 })
return Response.json({ messages })
} catch (err) {
if (err instanceof LeashError) {
switch (err.code) {
case 'UNAUTHORIZED':
return Response.json({ error: 'sign in' }, { status: 401 })
case 'INTEGRATION_NOT_ENABLED':
return Response.json({ error: 'connect gmail', connect: '/dashboard/integrations' }, { status: 403 })
case 'UPGRADE_REQUIRED':
return Response.json({ error: err.message, upgrade: '/dashboard/billing' }, { status: 402 })
default:
console.error(err.code, err.toString())
return Response.json({ error: err.message }, { status: 500 })
}
}
throw err
}
}

LeashError shape

class LeashError extends Error {
readonly code: LeashErrorCode
readonly action?: string // human-readable fix hint
readonly seeAlso?: string // doc URL
toString(): string // pretty: "× message\n Fix: action\n See: seeAlso"
}

Log err.toString() in dev — it surfaces the action and link directly. In prod, branch on err.code.

See also: SDK overview for the full surface.