Documentation Index Fetch the complete documentation index at: https://mintlify.com/honojs/hono/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Hono provides robust error handling mechanisms to help you manage both expected and unexpected errors in your applications. Proper error handling ensures your API returns meaningful responses and maintains stability.
HTTPException
The HTTPException class is the primary way to throw HTTP errors in Hono. It allows you to return specific HTTP status codes with custom messages.
Basic Usage
import { Hono } from 'hono'
import { HTTPException } from 'hono/http-exception'
const app = new Hono ()
app . post ( '/auth' , async ( c ) => {
const { username , password } = await c . req . json ()
const authorized = await verifyCredentials ( username , password )
if ( ! authorized ) {
throw new HTTPException ( 401 , {
message: 'Invalid credentials'
})
}
return c . json ({ message: 'Authenticated' })
})
HTTPException Options
The HTTPException constructor accepts:
status - HTTP status code (default: 500)
options.message - Error message
options.res - Custom Response object
options.cause - Original error cause
app . get ( '/users/:id' , async ( c ) => {
const id = c . req . param ( 'id' )
try {
const user = await db . users . findById ( id )
if ( ! user ) {
throw new HTTPException ( 404 , {
message: `User ${ id } not found`
})
}
return c . json ( user )
} catch ( error ) {
throw new HTTPException ( 500 , {
message: 'Database error' ,
cause: error
})
}
})
Custom Response
Return a custom Response object with the exception:
app . post ( '/api/data' , async ( c ) => {
const data = await c . req . json ()
if ( ! isValid ( data )) {
const res = new Response (
JSON . stringify ({
error: 'Validation failed' ,
details: getValidationErrors ( data )
}),
{
status: 400 ,
headers: { 'Content-Type' : 'application/json' }
}
)
throw new HTTPException ( 400 , { res })
}
return c . json ({ success: true })
})
Global Error Handler
Define a custom error handler to catch all errors in your application:
import { Hono } from 'hono'
import { HTTPException } from 'hono/http-exception'
const app = new Hono ()
app . onError (( err , c ) => {
if ( err instanceof HTTPException ) {
// Get the custom response
return err . getResponse ()
}
// Handle other errors
console . error ( ` ${ err } ` )
return c . text ( 'Internal Server Error' , 500 )
})
app . get ( '/' , ( c ) => {
throw new Error ( 'Something went wrong!' )
})
Structured Error Responses
Return consistent error response structures:
app . onError (( err , c ) => {
if ( err instanceof HTTPException ) {
return c . json (
{
error: {
message: err . message ,
status: err . status ,
},
},
err . status
)
}
return c . json (
{
error: {
message: 'Internal Server Error' ,
status: 500 ,
},
},
500
)
})
NotFound Handler
Handle 404 errors with a custom not found handler:
const app = new Hono ()
app . notFound (( c ) => {
return c . text ( 'Custom 404 Message' , 404 )
})
// Or return JSON
app . notFound (( c ) => {
return c . json (
{
error: 'Not Found' ,
path: c . req . path ,
},
404
)
})
Error Handling Middleware
Create middleware to handle errors for specific routes:
const errorHandlingMiddleware = async ( c , next ) => {
try {
await next ()
} catch ( error ) {
if ( error instanceof HTTPException ) {
return error . getResponse ()
}
// Log error
console . error ( 'Unexpected error:' , error )
// Return generic error
return c . json (
{ error: 'An unexpected error occurred' },
500
)
}
}
app . use ( '/api/*' , errorHandlingMiddleware )
Validation Errors
Handle validation errors from the validator middleware:
import { validator } from 'hono/validator'
app . post (
'/users' ,
validator ( 'json' , ( value , c ) => {
const data = value as { email : string ; age : number }
const errors = []
if ( ! data . email || ! data . email . includes ( '@' )) {
errors . push ( 'Invalid email' )
}
if ( data . age < 18 ) {
errors . push ( 'Must be 18 or older' )
}
if ( errors . length > 0 ) {
return c . json ({ errors }, 400 )
}
return data
}),
( c ) => {
const user = c . req . valid ( 'json' )
return c . json ({ created: true , user })
}
)
Async Error Handling
Handle errors in async handlers:
app . get ( '/data' , async ( c ) => {
try {
const data = await fetchExternalAPI ()
return c . json ( data )
} catch ( error ) {
if ( error . code === 'TIMEOUT' ) {
throw new HTTPException ( 504 , {
message: 'Gateway Timeout'
})
}
if ( error . code === 'NOT_FOUND' ) {
throw new HTTPException ( 404 , {
message: 'Resource not found'
})
}
throw new HTTPException ( 500 , {
message: 'Failed to fetch data' ,
cause: error
})
}
})
Status Codes
Common HTTP status codes for errors:
400 - Bad Request (validation errors)
401 - Unauthorized (authentication required)
403 - Forbidden (insufficient permissions)
404 - Not Found (resource doesn’t exist)
409 - Conflict (resource conflict)
422 - Unprocessable Entity (semantic errors)
429 - Too Many Requests (rate limiting)
500 - Internal Server Error (server errors)
503 - Service Unavailable (temporary issues)
Best Practices
Use appropriate status codes
Choose the correct HTTP status code that accurately represents the error condition.
Provide helpful error messages
Include clear, actionable error messages that help users understand what went wrong.
Always log errors server-side for debugging, but don’t expose internal details to clients.
Handle errors consistently
Use a global error handler to ensure consistent error response format across your API.
Don't expose sensitive information
Never include sensitive information like stack traces or internal paths in production error responses.