H
Hono6mo ago
Davis

How to set up and use a structured error format?

Hi; I am not strong in API design, and had a question about structuring error formats. I wish to create error formats, that are extensions of the Error instance, let's all it MY_API_ERROR_INSTANCE Something like:
c.json({
message: "The route/endpoint you are looking for does not exist. It may have been removed or moved to a different location.",
type: "Not Found",
types: ["Not Found", "Error"],
status: 404,
cause: { ...recurse for nested any exceptions... }
})
c.json({
message: "The route/endpoint you are looking for does not exist. It may have been removed or moved to a different location.",
type: "Not Found",
types: ["Not Found", "Error"],
status: 404,
cause: { ...recurse for nested any exceptions... }
})
But I don't wish to always type this out, and I also want to create a type-safe and generic one, in that it can accommodate different types of responses & statuses. Has anyone implemented something like this, or has any resources they can share about this kind of API design? I appreciate the help. P.S. For context, I am building targeting Cloudflare Workers, Neon, Drizzle... if that helps with some context.
1 Reply
Mickaël
Mickaël6mo ago
Hi, a solution for this problem is to catch all errors and format them in one place, like this :
const app = new Hono()
.onError((error, c) => {
if (error.status === 404) {
return c.req.path.startsWith('/api/')
? c.json(
{
error: {
code: 'NotFound',
message: error.message ?? 'Entity not found',
},
},
404,
)
: c.html(<NotFoundPage />, 404)
}
}
...the same for all status code you like to support...
return c.req.path.startsWith('/api/')
? c.json(
{
error: {
code: 'ServerError',
message: 'An unknown error occurred',
},
},
500,
)
: c.html(<ServerErrorPage />, 500)
})
.notFound((c) =>
c.req.path.startsWith('/api/')
? c.json(
{
error: {
code: 'ApiNotFound',
message: 'Api not found',
},
},
404,
)
: c.html(<NotFoundPage />, 404),
)
const app = new Hono()
.onError((error, c) => {
if (error.status === 404) {
return c.req.path.startsWith('/api/')
? c.json(
{
error: {
code: 'NotFound',
message: error.message ?? 'Entity not found',
},
},
404,
)
: c.html(<NotFoundPage />, 404)
}
}
...the same for all status code you like to support...
return c.req.path.startsWith('/api/')
? c.json(
{
error: {
code: 'ServerError',
message: 'An unknown error occurred',
},
},
500,
)
: c.html(<ServerErrorPage />, 500)
})
.notFound((c) =>
c.req.path.startsWith('/api/')
? c.json(
{
error: {
code: 'ApiNotFound',
message: 'Api not found',
},
},
404,
)
: c.html(<NotFoundPage />, 404),
)
So when you throw an error like this :
import { HTTPException } from 'hono/http-exception'

throw new HTTPException(404, { message: `Product ${id} not found` })
import { HTTPException } from 'hono/http-exception'

throw new HTTPException(404, { message: `Product ${id} not found` })
The error is formatted to your app standard error format. Another one is create some classes that extends HTTPException, if you want type safety and more complex error objects.
Want results from more Discord servers?
Add your server