@easyweb/errors

中文文档
1.1.0发布于 2026/08/14MITTypeScriptESM + CJS零依赖近 30 天下载 3410

Shared HTTP error taxonomy for Easyweb microservices: typed error classes with machine-readable codes, and the express error-handling middleware that serializes them

原始使用文档
文档目录8 节
  1. Install
  2. Wiring
  3. Response shape
  4. Classes
  5. Picking one
  6. Behaviour of the handler
  7. isCustomError
  8. Publishing

@easyweb/errors

Shared HTTP error taxonomy for Easyweb microservices: typed error classes with machine-readable codes, and the express middleware that serializes them.

Previously these classes lived in @easyweb/authentication. They moved here in @easyweb/[email protected] — error handling is cross-cutting, and a service that needs ConflictError should not have to depend on a JWT package to get it.

Install

npm install @easyweb/errors

express@^5 is a peer dependency, owned by the consuming service.

Wiring

Mount the catch-all and the handler last, after every router:

import { errorHandler, notFoundHandler } from "@easyweb/errors";
import logger from "./lib/logger";

app.use("/auth", authRouter);

app.all(/.*/, notFoundHandler);
app.use(errorHandler({ logger }));

Pass the service's pino instance. The default is console, which works but produces unstructured output with no service name, no redaction, and no request id.

OptionDefault
loggerconsoleAnything with error and warn.
logClientErrorsfalseLog 4xx at warn level. Off because client mistakes are not incidents.
includeRequestIdtrueInclude requestId in the body.
fallbackMessage"Something went wrong"Body text for an unrecognized error.

Response shape

{
  "errors": [
    { "message": "Email is already registered", "field": "email", "code": "CONFLICT" }
  ],
  "requestId": "0f4d…"   // omitted when requestContext has not run
}

message and field predate this package and are unchanged. code is additive and is the only part clients should branch on — message is free-form English written at the throw site, and some of it is already Indonesian.

requestId comes from req.requestId, set by requestContext in @easyweb/authentication, and matches the x-request-id response header. It is read defensively, so this package does not depend on the auth package.

Classes

StatusClassConstructor
400BadRequestError(message)
400RequestValidationError(errors) — accepts { field, message } or { msg, path }, per entry
401NotAuthorizedError(message = "Not authorized")
403ForbiddenError(message = "Forbidden")
404NotFoundError() — unrouted path
404ResourceNotFoundError(resource, id?) — domain object
409ConflictError(message, field?)
422UnprocessableEntityError(message)
429TooManyRequestsError(message?, retryAfterSeconds?)
500InternalServerError(message = "Something went wrong")
500DatabaseConnectionError()
502BadGatewayError(message?)
503ServiceUnavailableError(message?, retryAfterSeconds?)
504GatewayTimeoutError(message?)

retryAfterSeconds becomes a Retry-After header.

Picking one

  • 401 vs 403 — 401 means "we do not know who you are"; 403 means "we do, and you may not". Returning 401 for a role failure sends the client round a re-authentication loop that cannot succeed.
  • 400 vs 409 — 400 says the request was malformed. If the request was fine and the state conflicts (duplicate email, already-verified account), that is 409: retrying the identical request cannot help.
  • 400 vs 404 — BadRequestError("User not found") blames the caller for asking about something absent. Use ResourceNotFoundError. Exception: during login, "no such user" is a NotAuthorizedError, or the endpoint becomes an account-enumeration oracle.
  • 500 vs 503 — 500 means our code broke. A dependency being temporarily down is 503, and orchestrators treat the two differently.

Behaviour of the handler

  1. A CustomError is serialized with its own status and body.
  2. A body-parser SyntaxError (malformed JSON) becomes 400, not 500.
  3. A non-CustomError carrying a numeric status / statusCode in [400,599] keeps it — several libraries in the stack set an accurate one.
  4. Anything else is 500 with fallbackMessage.

On branches 2–4 the original message and stack are never serialized: they may name a table, a query, or a secret. Only the status is trusted.

isCustomError

The handler branches on isCustomError(err), not err instanceof CustomError.

instanceof compares constructor identity, so it fails when two copies of this package exist in one process — for example a nested install under node_modules/@easyweb/authentication/node_modules/. The failure is silent and total: every error stops matching and turns into a generic 500, while types still check and the build still passes.

Two defences: @easyweb/authentication declares this package as a peerDependency so npm cannot nest it, and CustomError carries a __easywebError brand that isCustomError falls back to. If you add a package that depends on this one, declare it as a peer for the same reason.

Verify with:

npm ls @easyweb/errors    # must show exactly one, deduped at the top level

Publishing

npm run build && npm publish

build runs clean first. Without it a renamed or deleted source file leaves an orphan in dist/ that ships in the tarball.

版本与发布记录

@easyweb/errors 共发布 2 个版本,首次发布于 2026/08/06;过去 12 个月发布了 2 个版本。

版本发布日期距今
1.1.0latest2026/08/142 个月前
1.0.02026/08/063 个月前

关于 @easyweb/errors 的常见问题

@easyweb/errors 是什么?

Shared HTTP error taxonomy for Easyweb microservices: typed error classes with machine-readable codes, and the express error-handling middleware that serializes them

如何安装 @easyweb/errors?

在项目目录运行 npm install @easyweb/errors,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:express(^5.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@easyweb/errors 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@easyweb/errors 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@easyweb/errors 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@easyweb/errors 可以商用吗?

@easyweb/errors 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@easyweb/errors 的下载量有多少?

根据 npm 官方下载统计,@easyweb/errors 在 2026/10/13 – 2026/11/11 这 30 天内被下载 3,410 次,日均约 114 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@easyweb/errors 还在维护吗?

最新版本 1.1.0 发布于 2026/08/14(2 个月前);至今共发布 2 个版本,其中过去 12 个月发布了 2 个;首次发布于 2026/08/06。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。