Skip to main content

Errors

Every failure in @cstar.help/js throws a CStarError subclass. Catch by class — strings rotate; class identity doesn't. Every error carries a request ID; paste it into a support ticket and we find the call in seconds.

Catch by class

Match on the typed subclass and recover differently per case. instanceof works across every subpath import — /auth, /library, /community, /quickhelp, /proactive — because the class identity is registered on a Symbol.for(...) slot of globalThis. Bundle splits don't break the check.

catch-by-class.js
import {
  CStarError,
  CStarValidationError,
  CStarRateLimitError,
  CStarAuthenticationError
} from '@cstar.help/js';

try {
  await cstar.tickets.create(formData);
} catch (e) {
  if (e instanceof CStarValidationError) {
    // e.param holds the offending field name
    return showFieldError(e.param, e.message);
  }
  if (e instanceof CStarRateLimitError) {
    return retryAfter(e.retryAfter); // seconds, default 60
  }
  if (e instanceof CStarAuthenticationError) {
    // Bad/expired key. Bounce the user to settings.
    return redirectToKeyRotation();
  }
  if (e instanceof CStarError) {
    // Catch-all for any other typed cStar error.
    log.error('cStar call failed', {
      code: e.code,
      requestId: e.requestId,
      docUrl: e.docUrl,
      statusCode: e.statusCode
    });
  }
  throw e;
}

Every error carries

The base class fields land on every subclass. Most of what you need to file a support ticket is already there.

The subclasses

Eight typed subclasses, dispatched by HTTP status and error type.

CStarAuthenticationError 401

Missing or invalid API key. Bad Authorization header.

CStarPermissionError 403

Wrong key type for the operation, or your role lacks the permission.

CStarNotFoundError 404

The resource ID doesn't exist (or your key can't see it).

CStarValidationError 400 / 422

Bad payload. e.param holds the field name.

CStarConflictError 409

Idempotency replay or unique-key conflict.

CStarRateLimitError 429

e.retryAfter tells you how many seconds to wait (default 60).

CStarServerError 5xx

Our problem. Retry once with backoff; ping support with the request ID if it persists.

CStarFeatureNotConfiguredError 409

The team hasn't enabled the feature this call needs (e.g. AI). e.feature + e.enableUrl tell you where to go.

Request IDs

Every error carries requestId. So does every successful response, via cstar.lastMeta.requestId. Both pull from the same source — the x-cstar-request-id header that every cStar response emits.

logging.js
try {
  const ticket = await cstar.tickets.create(payload);
  log.info('ticket created', {
    ticketId: ticket.id,
    requestId: cstar.lastMeta.requestId
  });
} catch (e) {
  // Always log the request ID. Always.
  log.error('ticket.create failed', {
    code: e.code,
    requestId: e.requestId,
    docUrl: e.docUrl
  });
  throw e;
}

Cross-subpath identity

The error classes live on globalThis[Symbol.for('@cstar.help/js/errors/v1')]. That means an error thrown by LibraryClient (imported from @cstar.help/js/library) and caught with CStarError imported from the root entry — different bundles, different module copies — still resolves to the same class identity at runtime. instanceof works across every subpath.

Each subpath also re-exports the canonical error classes for ergonomics, so you can import { CStarError } from '@cstar.help/js/library' if you prefer.

Next up