universal-api-errors
v0.1 · core, Axios & fetch adapters shipped

One error object.
No matter where it came from.

Axios, fetch, or anything else — universal-api-errors normalizes it into one predictable, fully-typed shape. Stop writing if (error.response?.status === 401) in every project.

Only need Axios or fetch, not both? Install just the one adapter instead.

npm versionweekly downloadsGitHub starslicenseTypeScript

Every project re-writes this

A different pile of ifchecks per backend, per project, forever — because every API spells "unauthorized" differently.

Before

try {  await api.getUser(id);} catch (error) {  if (error.response?.status === 401) {    // ...  }  if (error.response?.data?.message) {    // ...  }  if (error.code === "ERR_NETWORK") {    // ...  }  if (error.message.includes("timeout")) {    // ...  }  // every backend spells these differently — repeat per project}

After

import { parseAxiosError } from "@harshilrajput/universal-api-errors-axios";try {  await api.getUser(id);} catch (err) {  const error = parseAxiosError(err);  error.message;         // "Token Expired"  error.status;          // 401  error.retryable;       // false  error.isUnauthorized;  // true}

What's actually in the box

Everything below is shipped, tested, and published — not a roadmap slide.

Universal parser
parseError() recognizes Axios, ky, and superagent's error shape, Node's error codes, and fetch's network-failure messages via duck-typing — no adapter required.
TypeScript-first
Strict mode throughout, including exactOptionalPropertyTypes and noUncheckedIndexedAccess. Zero any in the public API.
Retry helpers
retry() with fixed or exponential backoff and full jitter by default, plus error.shouldRetry() on every parsed error.
Validation parsing
normalizeValidation() folds Laravel, Rails, express-validator, and FastAPI's different validation-error shapes into one { field: string[] } map.
Smart detection
isOffline, isTimeout, isDNS, isSSL, isCors, isRateLimited, isCancelled — classified consistently from status codes and error codes, not guessed per adapter.
Zero dependencies
The core package has no runtime dependencies at all — not even Axios's types. It's usable standalone, tree-shakeable, and small.
Logging & debug mode
error.debug() prints a readable console block; error.log() emits structured JSON with secret redaction on by default.
Framework agnostic
One UniversalError model extends the real Error class, so instanceof, throw, and error-reporting SDKs keep working exactly as they already do.

Works with what you already use

Dedicated adapters for Axios and fetch, plus a React Query integration. The core parser also duck-types ky, superagent, and Node's error codes — no adapter needed for those.

Building an adapter for something else? See what's planned or open an issue on GitHub.

The same shape, every time

Pick your client — the output is identical.

import axios from "axios";import { parseAxiosError } from "@harshilrajput/universal-api-errors-axios";try {  await axios.get("/api/user");} catch (err) {  const error = parseAxiosError(err);  if (error.isUnauthorized) return redirectToLogin();  if (error.isValidation) return showFieldErrors(error.validation);  if (error.shouldRetry()) return retry();  showToast(error.message);}