API Problem Details for HTTP APIs
raw JSON →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
error TypeError: Problem is not a constructor ↓
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 Error: The 'api-problem' package requires Node.js version 14 or higher. You are running Node.js version X. ↓
error Type 'typeof import("api-problem").Problem' is not assignable to type 'Problem'. Did you mean to use 'typeof import("api-problem").Problem'? ↓
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) wrong
import { Problem } from 'api-problem'correctimport Problem from 'api-problem' - Problem (CommonJS) wrong
import Problem from 'api-problem'correctconst Problem = require('api-problem') - Problem Type (TypeScript) wrong
import { Problem } from 'api-problem' // for type-only importcorrectimport 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)