JavaScript clientError handling

Error handling

Every client throws an ApiError when a request fails. It extends Error and carries the HTTP status and any validation detail returned by the API.

import { ApiError } from '@devium/rms';

export class ApiError extends Error {
  status?: number;          // HTTP status code, e.g. 404
  statusText?: string;      // HTTP status text, e.g. "Not Found"
  validationErrors?: HTTPValidationError; // { detail?: string }
}

Catching errors

import { ApiError } from '@devium/rms';

try {
  const pool = await resources.getPool(poolId);
} catch (err) {
  if (err instanceof ApiError) {
    console.error(`Request failed (${err.status} ${err.statusText}): ${err.message}`);
    if (err.validationErrors?.detail) {
      console.error('Validation:', err.validationErrors.detail);
    }
  } else {
    throw err; // network/unexpected error
  }
}

Handling expired tokens

A 401 means the access token is missing or expired. Use the auth client to refresh and retry:

import { ApiError } from '@devium/rms';

async function withAuth<T>(call: () => Promise<T>): Promise<T> {
  try {
    return await call();
  } catch (err) {
    if (err instanceof ApiError && err.status === 401) {
      const { accessToken } = await auth.refresh();
      resources.setAccessToken(accessToken);
      return call(); // retry once
    }
    throw err;
  }
}

const pools = await withAuth(() => resources.getAllPools());

For long-lived sessions, prefer auth.ensureValidToken() (refreshes proactively when the token is near expiry) or auth.loginWithAutoRefresh(...) so you rarely hit a 401 in the first place — see Authentication.

Common statuses

StatusMeaningTypical fix
400Bad requestCheck the request body shape
401UnauthenticatedRefresh or re-issue the access token
403ForbiddenThe user lacks permission for this resource
404Not foundVerify the id / path
422Validation errorInspect err.validationErrors.detail