> ## 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.

# Error Handling

> Learn how to handle errors gracefully in your Hono applications.

## 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

```typescript theme={null}
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

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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:

```typescript theme={null}
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

<AccordionGroup>
  <Accordion title="Use appropriate status codes">
    Choose the correct HTTP status code that accurately represents the error condition.
  </Accordion>

  <Accordion title="Provide helpful error messages">
    Include clear, actionable error messages that help users understand what went wrong.
  </Accordion>

  <Accordion title="Log errors for debugging">
    Always log errors server-side for debugging, but don't expose internal details to clients.
  </Accordion>

  <Accordion title="Handle errors consistently">
    Use a global error handler to ensure consistent error response format across your API.
  </Accordion>

  <Accordion title="Don't expose sensitive information">
    Never include sensitive information like stack traces or internal paths in production error responses.
  </Accordion>
</AccordionGroup>

## Related

* [Validation](/guides/validation) - Validate input and handle validation errors
* [Middleware](/middleware/overview) - Create error handling middleware
* [TypeScript](/guides/typescript) - Type-safe error handling
