Mr. Doge

Concepts

Error handling

Typed error classes, abort signals, and rate-limit recovery.

The SDK throws typed errors for everything the server can return, plus a few client-side ones (network failures, aborts). Catch them with instanceof.

Error classes

Re-exported from @mrdoge/node and @mrdoge/client:

ClassWire codeWhen
ValidationErrorinvalid_paramsSchema rejected your params
AuthEndpointError@mrdoge/client only — your token-mint route is down or returned non-2xx
UnauthorizedErrorunauthorizedInvalid/revoked key, expired JWT
ForbiddenErrorforbiddenMethod not in your tier
NotFoundErrornot_foundResource doesn't exist
RateLimitErrorrate_limitedToo many requests per minute
SubscriptionLimitErrorsubscription_limit_exceededToo many concurrent subscriptions
ConnectionLimitErrorconnection_limit_exceededToo many WebSocket connections
UnavailableErrorunavailableServer temporarily down
InternalErrorinternal_errorServer bug or transient failure
ProtocolErrorinvalid_request / method_not_foundFrame-level violation
ConnectionErrorWebSocket couldn't connect
DisconnectedErrorConnection dropped mid-request
TimeoutErrorRequest exceeded requestTimeoutMs (default 10s)
AbortErrorUser aborted via AbortSignal

All classes extend MrDogeError, which extends Error.

Basic catch

import {
  RateLimitError,
  UnauthorizedError,
  ForbiddenError,
} from "@mrdoge/node";

try {
  const { data } = await mrdoge.ai.picks.list({ date: "2026-05-18" });
} catch (err) {
  if (err instanceof UnauthorizedError) {
    // refresh token / re-auth
  } else if (err instanceof ForbiddenError) {
    // upgrade tier — err.data exposes method + tier context
  } else if (err instanceof RateLimitError) {
    // back off and retry
  } else {
    throw err;
  }
}

Rate limits

When you hit a limit, the server returns rate_limited with metadata. The SDK exposes it on the error's data field:

catch (err) {
  if (err instanceof RateLimitError) {
    console.log("Rate limited. Data:", err.data);
    // wait and retry
  }
}

See tiers & limits for per-tier numbers.

Abort

All methods accept options.signal for native abort support:

import { AbortError } from "@mrdoge/node";

const controller = new AbortController();
setTimeout(() => controller.abort(), 1000);

try {
  await mrdoge.matches.list(
    { sports: ["soccer"] },
    { signal: controller.signal },
  );
} catch (err) {
  if (err instanceof AbortError || err.name === "AbortError") {
    // user navigated away, request cancelled
  }
}

AbortError matches the fetch convention — err.name === "AbortError" is true.

Validation errors

ValidationError is what the SDK throws when your params don't match the protocol schema:

catch (err) {
  if (err instanceof ValidationError) {
    console.log(err.message);
    console.log(err.data); // array of validation issues
  }
}

In dev this usually means a typo or a wrong type. In prod, treat it as a bug — TypeScript types prevent most of these.

Subscription errors

Subscriptions deliver errors via the closed event, not as thrown exceptions on subscribeLive:

const sub = await mrdoge.matches.subscribeLive({ sports: ["soccer"] });

sub.on("closed", ({ reason, message }) => {
  console.log("Subscription closed:", reason, message);
  // "user_cancelled" | "rate_limited" | "internal_error" | "unauthorized" | ...
});

If the subscription never opens (you're rate-limited at subscribe time), subscribeLive throws SubscriptionLimitError or similar — handle in the try/catch around await mrdoge.matches.subscribeLive(...).

Next

On this page

Error handling