API Problem Details for HTTP APIs
api-problem is a JavaScript utility library designed to standardize error responses in HTTP APIs according to RFC 7807, "Problem Details for HTTP APIs." It provides a `Problem` class that allows developers to construct detailed, machine-readable error objects for various HTTP status codes. These objects include a status, human-readable title, a URI identifying the problem type (which defaults to MDN HTTP status pages since v9), and optional additional fields. The current stable version is 9.0.2. The library maintains an active release cadence, primarily focusing on security updates, dependency bumps, CI/CD improvements, and dropping support for older Node.js versions to align with modern JavaScript ecosystems. Its core differentiator is strict adherence to the RFC 7807 specification, ensuring consistent and interoperable error communication across different API clients and servers.
Common errors
-
TypeError: Problem is not a constructor
cause This error often occurs when attempting to instantiate `Problem` as a class using incorrect module import syntax, such as `import { Problem } from 'api-problem'` in an ESM context, or when using `require()` in an environment expecting ESM default imports without proper configuration.fixFor ES Modules, use `import Problem from 'api-problem'`. For CommonJS, use `const Problem = require('api-problem')`. Verify your project's `package.json` `"type"` field and file extensions (.js vs .mjs vs .cjs) to ensure consistent module resolution. -
Error: The 'api-problem' package requires Node.js version 14 or higher. You are running Node.js version X.
cause Attempting to run `api-problem` versions 8.0.0 or later on a Node.js runtime older than v14.fixUpgrade your Node.js development and deployment environments to version 14 or newer. Consult the official Node.js website for long-term support (LTS) releases and upgrade procedures. -
Type 'typeof import("api-problem").Problem' is not assignable to type 'Problem'. Did you mean to use 'typeof import("api-problem").Problem'?cause In a TypeScript project, this error indicates an incorrect import for the `Problem` type, typically trying to import it as a named export (`import { Problem } from '...'`) when it is a default export.fixTo correctly import the type for the default-exported `Problem` class in TypeScript, use `import type Problem from 'api-problem';`.
Warnings
- breaking The default domain for the 'type' field in `Problem` objects changed from `about:blank` (or similar, sometimes omitted) to `https://developer.mozilla.org/` for HTTP status-related problem types. This change affects the URI structure when a custom `type` is not explicitly provided.
- breaking Support for Node.js v12 was officially dropped. Projects using `api-problem` v8.0.0 or later are required to run on Node.js v14 or higher.
- breaking The library removed older Babel-generated, targeted builds (e.g., for ES5 compatibility), transitioning to ES2015+ as its primary output. While CommonJS compatibility is maintained, projects targeting very old Node.js runtimes or specific non-ES2015 environments might face compatibility issues if they relied on these older builds.
- gotcha A prototype pollution vulnerability (CVE-2022-46175) in the `json5` dependency was addressed in a patch release. While `api-problem`'s direct usage of `json5` might be limited, it's critical to update to mitigate potential supply chain attacks or other vulnerabilities if your project also processes untrusted JSON5 data.
Install
-
npm install api-problem -
yarn add api-problem -
pnpm add api-problem
Imports
- Problem (ESM)
import { Problem } from 'api-problem'import Problem from 'api-problem'
- Problem (CommonJS)
import Problem from 'api-problem'
const Problem = require('api-problem') - Problem Type (TypeScript)
import { Problem } from 'api-problem' // for type-only importimport type Problem from 'api-problem'
Quickstart
import Problem from 'api-problem';
import http from 'http';
// Create a basic 404 Not Found problem
const notFoundProblem = new Problem(404);
console.log('Basic 404 Problem:', notFoundProblem.toObject());
// Create a 403 Forbidden problem with a custom title
const forbiddenProblem = new Problem(403, 'Access to resource denied');
console.log('Custom Title Problem:', forbiddenProblem.toObject());
// Create a custom problem type with additional details
const outOfCreditProblem = new Problem(
403,
'You do not have enough credit',
'https://example.com/probs/out-of-credit',
{
detail: 'Your current balance is 30, but that costs 50 for this operation.',
instance: '/account/12345/transactions/abc',
balance: 30
}
);
console.log('Custom Detailed Problem:', outOfCreditProblem.toObject());
// Example of sending a problem via an HTTP response (Node.js http module)
const server = http.createServer((req, res) => {
if (req.url === '/error') {
const problem = new Problem(400, 'Invalid parameters in request', 'https://example.com/probs/invalid-params', {
errors: [
{ field: 'param1', message: 'Must be a number' },
{ field: 'param2', message: 'Cannot be empty' }
]
});
problem.send(res);
} else {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World');
}
});
// server.listen(3000, () => console.log('Server running on http://localhost:3000'));
// To test: curl -i http://localhost:3000/error
// (Uncomment server.listen and run the file to test the .send() method)