Enlitt

Typed errors

Every Enlitt failure is a typed, non-retryable refusal. Half are safe to show a user; half must stay in your logs.

Every Enlitt-originated failure — standard or premium — extends one base class, EnlittError, and carries a stable code. Admission refusals arrive as typed, non-retryable errors, not as a call outcome your code has to inspect a result shape to notice: catch them like any other thrown error.

readonly providerInvoked: boolean; // always false on this hierarchy
readonly retryable: boolean;       // false for every refusal except rate limiting
readonly code: string;
readonly retryAfterMs?: number;
readonly requestId?: string;
readonly authorizeUrl?: string;    // only on the four credit/limit errors below

providerInvoked is always false on every instance of this hierarchy: Enlitt refuses before a provider is ever reached, so this hierarchy never represents a provider's own failure. A provider's own error (a bad completion, a provider-side 500) is rethrown unchanged, with its original type — it is never wrapped as an EnlittError.

The audience split

This is the one distinction to get right before you show any Enlitt error to anyone: some codes are the end user's business, and some are yours alone.

Safe to render directly to the end user

ClassCodeWhat it means
EnlittLoginRequiredErrorpersonal_login_requiredNo usable personal session. Send the user through login or reauthorization.
EnlittLimitExceededErrorpremium_per_call_limit_exceededThis call exceeds the user's own per-call premium ceiling. See Premium limits.
EnlittInsufficientCreditsErrorpremium_balance_exhausted, standard_balance_exhaustedThe user's premium ceiling, or their plan's standard ceiling, is reached for the period.
EnlittSubscriptionInactiveErrorsubscription_inactiveNo subscription period covers now. Every registered user holds at least the free plan, so this is exceptional — treat it as a defect signal, not an ordinary funnel step, if you see it at any volume.

None of these four carry the user's actual balance, remaining capacity, plan, or period — that is the user's own private financial position. The first three may carry authorizeUrl, a navigation target to Enlitt's own screen where the user can act and see the real numbers; your UI links to it, it never mirrors the figures behind it.

Business logs only — never render to an end user

ClassCodeWhat it means
EnlittConfigurationErrorconfiguration_invalidMissing/invalid secret, browser use, bad base URL, bad call options, missing session context. Thrown locally, before any network call.
EnlittAuthenticationErrorinvalid_api_keyThe presented business key is missing, invalid, or revoked.
EnlittAuthorizationErrorinsufficient_permissionsThe presented business key is valid but used outside its authenticated application or scope.

These three describe a problem with your integration, not the user's account or the request they made. Showing one to an end user leaks nothing financial, but it is meaningless and alarming to them — it belongs in your own error tracking.

Retryable, and everything else

EnlittRateLimitError (rate_limit_exceeded) is the only retryable refusal, and the only class that carries retryAfterMs in practice. It is deliberately not an EnlittInsufficientCreditsError: conflating a transient per-minute wait with an exhausted balance would tell a user to buy credits they do not need.

Every other wire code with no distinct business action of its own — conflict_error, operation_in_progress, idempotency_replay_unavailable, invalid_value, unsupported_parameter, unsupported_value, reauthentication_required, not_found, request_too_large, server_error, provider_error, no_capable_route — surfaces as the base EnlittError class directly, carrying that code. A wire code newer than your installed SDK version also degrades to this base class rather than throwing an unrecognized-type error, so an older SDK build keeps working against a backend that has since added one more code.

Checking a code

import { EnlittError, EnlittInsufficientCreditsError } from "@enlitt/sdk/server";

catch (error) {
  if (error instanceof EnlittInsufficientCreditsError) {
    // error.code is "premium_balance_exhausted" or "standard_balance_exhausted"
  } else if (error instanceof EnlittError) {
    // any other Enlitt refusal — check error.code before deciding what, if
    // anything, to show the user
  } else {
    throw error; // not an Enlitt failure at all — a provider error, or a bug
  }
}

On this page