Wattfare / Docs
Dashboard
SDK reference

Error handling

Every SDK error extends WattfareError. The “not connected” case is the expected first-run path, so it's modeled as a branch — not a crash. Helpers recover typed errors even when the AI SDK wraps them.

Error classes

Typed subclasses are exported from every entry point (server, client, react).

ClasscodeHTTPWhen it happens
WattfareNotConnectedErrornot_connected402The user hasn't connected a budget to your app yet.
WattfareBudgetExceededErrorbudget_exceeded402Their monthly cap for this period is reached.
WattfareFundingErrorfunding_invalid402Their funding key was rejected upstream (revoked / out of credit). They must reconnect.
WattfareRateLimitErrorrate_limited429Too many requests. Back off and retry.
WattfareGrantErrorgrant_invalid402The one-time access grant is unknown, expired, fully used, or over its dollar cap.
WattfareAuthErrorauth401Invalid or missing credentials (secret key, session token…).
WattfareNetworkErrornetwork0Couldn't reach the Wattfare service at all.

A generic WattfareError also covers invalid_request, upstream (the model provider failed), and unknown.

error shape
// Every WattfareError serialises to this shape over the wire:
{ "error": { "code": "budget_exceeded", "message": "Spending cap reached for this period." } }

// And carries:
err.code    // WattfareErrorCode
err.status  // HTTP status it maps to
err.toJSON()

Helper functions

Reach for these instead of instanceof. They see through the AI SDK's APICallError wrapper, which would otherwise hide the real code.

FunctionReturnsUse it to…
toWattfareError(err)WattfareError | nullRecover a typed error from anything. null when unrelated to Wattfare.
isBudgetExceeded(err)booleanDetect a reached cap (even AI-SDK-wrapped).
isNotConnected(err)booleanDetect “user must (re)connect” — matches both not_connected and funding_invalid.

The canonical pattern

Handle the two actionable cases first, then fall back to the typed error's own status:

inference error handling
import { isNotConnected, isBudgetExceeded, toWattfareError } from "wattfare/server";

try {
  const result = await generateText({
    model: ai.model("anthropic/claude-sonnet-4"),
    prompt,
  });
  return Response.json({ text: result.text });
} catch (err) {
  if (isNotConnected(err))    return Response.json({ error: "connect_required" }, { status: 402 });
  if (isBudgetExceeded(err))  return Response.json({ error: "budget_reached" },   { status: 402 });

  const wf = toWattfareError(err);
  if (wf) return Response.json(wf.toJSON(), { status: wf.status });
  throw err; // genuinely unrelated — let it bubble
}

Branching on code

When you need finer control, read code off the recovered error:

code-level branching
import { toWattfareError } from "wattfare/server";

try {
  await generateText({ model: ai.model("openai/gpt-4o-mini"), prompt });
} catch (err) {
  // err is the AI SDK's APICallError — a plain instanceof check would miss it.
  const wf = toWattfareError(err);
  if (wf?.code === "budget_exceeded") return askUserToRaiseCap();
  if (wf?.code === "funding_invalid") return askUserToReconnect();
  throw err;
}

What to show users

ConditionUser-facing action
not_connectedShow the “Connect AI budget” button.
funding_invalidSame button, with a “reconnect — your funding needs attention” note.
budget_exceededShow usage vs. cap; link them to raise the cap in their dashboard.
grant_invalidShow a "Your access grant has been used up" message and offer to request a new one.
rate_limitedBack off (exponential) or show a brief “slow down” message.
network / upstreamRetry with backoff; surface a transient-error toast.
authA bug on your side — your secret key or session is wrong. Log and alert.