Skip to content

Sentry Errors

github-actions[bot] edited this page Oct 4, 2026 · 2 revisions

Sentry Errors

Sentry throws SentryError for invalid configuration, local request validation, and vendor responses — see errors/Base.ts and errors/SentryErrorCodes.ts. updateIssue()/createRelease() may also reject with a raw GuardianError (as error.cause) when the request itself fails local schema validation before any network call is made — see Schemas.

import { SentryError, SentryErrorCodes } from '@tundraconnect/sentry/errors';

const error = new SentryError('NOT_FOUND', { status: 404 });
console.log(error.message);
console.log(SentryErrorCodes.NOT_FOUND);

Codes

Sentry's documented error envelope ({ detail, causes? }, see Schemas) carries no machine-readable error code — only free-text detail. These codes are therefore connect-specific, keyed off the HTTP status Sentry actually returned (https://docs.sentry.io/api/), plus configuration and local request-validation failures that never come from the wire.

Code Meaning
CONFIG_INVALID_TOKEN auth is missing, isn't type: 'BEARER', or its token is blank/not a string.
CONFIG_INVALID_ORGANIZATION organization is missing, blank, or not a string.
INVALID_REQUEST Local request validation failed (before a request was sent), or Sentry returned 400 Bad Request.
AUTH_FAILED Sentry returned 401 Unauthorized.
FORBIDDEN Sentry returned 403 Forbidden (token scope/permissions).
NOT_FOUND Sentry returned 404 Not Found.
RATE_LIMITED Sentry returned 429 Too Many Requests.
RESPONSE_ERROR A success response's body failed schema validation.
SERVICE_UNAVAILABLE A 5xx response, or any response whose body didn't parse.
TIMEOUT Sentry did not answer within the client timeout (timeoutSeconds in context).
NETWORK_ERROR fetch failed before any response (DNS, TLS, connection reset); the transport error is the cause.
UNKNOWN_ERROR An unmapped status was returned, or an unknown code was supplied.

The resolved code is also available as a public, readonly error.code property — branch on failure mode without matching against .message:

if (error instanceof SentryError && error.code === 'RATE_LIMITED') {
  // ...
}

Use getContextValue() to read diagnostic metadata — never the token: this connect never places auth.token into an error's context or message, so error.message/error.toJSON() are always safe to log.

try {
  await client.listIssues();
} catch (error) {
  if (error instanceof SentryError) {
    console.log(error.getContextValue('status'));
    console.log(error.getContextValue('detail'));
  }
}

Rate limits

A 429 reads Sentry's documented rate-limit response headers (https://docs.sentry.io/api/ratelimits/) into the thrown error's context — rateLimitLimit, rateLimitRemaining, rateLimitReset (UTC seconds since epoch when the window resets), rateLimitConcurrentLimit, and rateLimitConcurrentRemaining. Sentry documents no Retry-After header for this endpoint family.

try {
  await client.listIssues();
} catch (error) {
  if (error instanceof SentryError && error.code === 'RATE_LIMITED') {
    const resetAt = error.getContextValue('rateLimitReset');
    console.log(`Retry after ${resetAt}`);
  }
}

Transient failures

TIMEOUT, NETWORK_ERROR, SERVICE_UNAVAILABLE and RATE_LIMITED mean "no answer yet": retrying later can help. Every other code is a definite refusal or a misconfiguration that retrying will not fix. Branch on the readonly err.transient, which is true for exactly these four, rather than listing codes yourself. The set is also exported as SENTRY_TRANSIENT_CODES from @tundraconnect/sentry/errors.

import { SentryError } from '@tundraconnect/sentry/errors';

declare function callTheClient(): Promise<unknown>;

try {
  await callTheClient();
} catch (err) {
  if (err instanceof SentryError && err.transient) {
    // queue it and try again later
  }
  throw err;
}
Context Present on Meaning
timeoutSeconds TIMEOUT The deadline that was missed, in seconds.

Backing off after a 429

A rate-limited request throws RATE_LIMITED. Two context values tell you what to do next:

Context Meaning
retryAfterSeconds Seconds the vendor asked you to wait, parsed by RESTler from Retry-After (delta seconds or an HTTP-date), X-RateLimit-Reset-After, RateLimit-Reset, or an epoch-seconds X-RateLimit-Reset. undefined when the response carried none — never a guess.
retried Set only when maxRetryWait is configured: true if RESTler already waited once and was throttled again, false if it did not wait (the hint exceeded the cap, or there was no hint to wait on).

Nothing is retried by default. Opt in with two client options (seconds, each 0–120):

  • maxRetryWait — when a 429 carries a hint no longer than this, RESTler waits that long and retries once; otherwise it throws RATE_LIMITED immediately. 0 disables the retry.
  • defaultRetryWait — the wait used when a 429 carries no hint. Without it a hintless 429 is never retried: RESTler does not invent a delay. Only consulted when maxRetryWait is set, and still capped by it.

← Back to Sentry

Clone this wiki locally