Dashboard

Error Handling

Handle API errors with typed error classes, automatic retries, and structured error responses.

Error Response Format

All API errors return a JSON object with a consistent structure:

{
  "error": "not_found",
  "message": "No NDC found for code 0000-0000-00",
  "code": "NDC_NOT_FOUND"
}
FieldTypeDescription
errorstringMachine-readable error type (e.g., "validation_error", "not_found")
messagestringHuman-readable description of what went wrong
codestring?Optional error code for specific error conditions

HTTP Status Codes

StatusError TypeWhen It Happens
400ValidationErrorInvalid input — missing required parameters, bad format
401AuthenticationErrorMissing or invalid API key / OAuth token
403ForbiddenErrorValid credentials but insufficient scopes
404NotFoundErrorThe requested resource does not exist
429RateLimitErrorPer-second rate limit exceeded
429QuotaExceededErrorMonthly quota exhausted
500ServerErrorInternal server error
502ServerErrorBad gateway
503ServerErrorService temporarily unavailable

SDK Typed Errors

The @fhirfly-io/terminology SDK maps every API error to a typed error class. This lets you handle specific error conditions without parsing status codes or response bodies.

Node.js
import {
  Fhirfly,
  NotFoundError,
  RateLimitError,
  ValidationError,
  AuthenticationError,
  QuotaExceededError,
} from "@fhirfly-io/terminology";

const client = new Fhirfly({ apiKey: "your-api-key" });

try {
  const ndc = await client.ndc.lookup("0000-0000-00");
} catch (err) {
  if (err instanceof NotFoundError) {
    // The code doesn't exist
    console.log(`Not found: ${err.code_type} ${err.code_value}`);
  } else if (err instanceof RateLimitError) {
    // Rate limited — SDK will auto-retry, but you can inspect details
    console.log(`Rate limited. Retry after: ${err.retryAfter}s`);
  } else if (err instanceof QuotaExceededError) {
    // Monthly quota exhausted — no auto-retry
    console.log(`Quota used: ${err.quotaUsed} / ${err.quotaLimit}`);
  } else if (err instanceof ValidationError) {
    // Bad input
    console.log(`Invalid input: ${err.message} (field: ${err.field})`);
  } else if (err instanceof AuthenticationError) {
    // Bad credentials
    console.log("Check your API key");
  } else {
    throw err; // Unexpected error
  }
}

Error Class Reference

ClassStatusKey Properties
ApiErroranystatusCode, code, details — base class for all API errors
AuthenticationError401Extends ApiError
ValidationError400field — the input field that failed validation
NotFoundError404code_type, code_value — what was looked up
RateLimitError429retryAfter, limit, remaining, reset
QuotaExceededError429quotaLimit, quotaUsed, quotaResetDate
ServerError5xxExtends ApiError
NetworkErrorcause — the underlying network error
TimeoutErrortimeoutMs — the timeout threshold that was exceeded

All typed error classes extend FhirflyError, which extends the standard Error class.

Retry Behavior

The SDK includes built-in retry logic with exponential backoff for transient errors:

Error TypeAuto-RetryNotes
RateLimitError (429)YesRespects Retry-After header
ServerError (5xx)YesUp to 3 retries with exponential backoff
NetworkErrorYesConnection failures, DNS errors
TimeoutErrorYesRequest timeouts
ValidationError (400)NoBad input — fix the request
AuthenticationError (401)NoBad credentials — fix the key
NotFoundError (404)NoResource doesn't exist
QuotaExceededError (429)NoMonthly quota exhausted

Configuring Retries

Node.js
const client = new Fhirfly({
  apiKey: "your-api-key",
  maxRetries: 5,      // Default: 3
  timeout: 30_000,    // Default: 10_000 (10 seconds)
});

Set maxRetries: 0 to disable automatic retries entirely.

Network Errors

NetworkError and TimeoutError are thrown when the SDK cannot reach the API server. These are not HTTP errors — they occur before any response is received.

Node.js
import { Fhirfly, NetworkError, TimeoutError } from "@fhirfly-io/terminology";

try {
  const result = await client.ndc.lookup("0069-0151-01");
} catch (err) {
  if (err instanceof TimeoutError) {
    console.log(`Request timed out after ${err.timeoutMs}ms`);
  } else if (err instanceof NetworkError) {
    console.log(`Network error: ${err.message}`);
    console.log(`Cause: ${err.cause?.message}`);
  }
}

See Also