Files
edgeever/apps/api/src/http-errors.ts
T
Dariusz Koryto 518fafa86e fix(api): report bad request bodies and fractional limits as client errors (#484)
A malformed JSON body, or a body over the route's size limit, made Hono
throw an HTTPException that the API reported as a 500 internal error. In
the companion API the same requests returned 503 "unavailable, please
retry", so clients retried a request that could never succeed. These
now return 400 bad_request and 413 payload_too_large in the API's usual
error shape.

A fractional limit or offset such as ?limit=1.5 was passed to SQLite as
a float and failed with a datatype mismatch. Limits, offsets and cursors
are now truncated to whole numbers, and the two private copies of the
clamp helper reuse the shared one.
2026-10-06 21:39:22 +08:00

56 lines
1.8 KiB
TypeScript

import type { Context } from "hono";
import { HTTPException } from "hono/http-exception";
export const apiError = (c: Context, code: string, message: string, status: number) =>
c.json(
{
error: {
code,
message,
},
},
status as 400
);
export const notFound = (c: Context, message: string) =>
apiError(c, "not_found", message, 404);
export const badRequest = (c: Context, message: string) =>
apiError(c, "bad_request", message, 400);
export const authNotConfigured = (c: Context) =>
apiError(
c,
"auth_not_configured",
"Authentication is not configured. Set EDGE_EVER_AUTH_PASSWORD as a Worker Secret and redeploy.",
503,
);
export const databaseNotReady = (c: Context) =>
apiError(
c,
"database_not_ready",
"Database is not ready. Bind the D1 database as DB and apply the remote migrations.",
503,
);
export const conflict = (c: Context, code: string, message: string) =>
apiError(c, code, message, 409);
export const unauthorized = (c: Context, message: string) =>
apiError(c, "unauthorized", message, 401);
export const forbidden = (c: Context, message: string) =>
apiError(c, "forbidden", message, 403);
// Hono middleware (JSON validation, body limits) rejects bad requests by
// throwing HTTPException. Report those as client errors in the API's error
// shape instead of letting them surface as an internal server error.
export const httpExceptionError = (c: Context, error: unknown) => {
if (!(error instanceof HTTPException) || error.status < 400 || error.status >= 500) return null;
if (error.status === 413) {
return apiError(c, "payload_too_large", "The request body is too large.", 413);
}
return apiError(c, "bad_request", error.message || "The request could not be read.", error.status);
};