> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/unjs/ofetch/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Automatic error throwing for failed requests with detailed error information and error data access

ofetch automatically throws errors for failed HTTP requests (status codes 400-599), making error handling straightforward and consistent.

## Automatic Error Throwing

Unlike native `fetch`, ofetch automatically throws errors when the response status is 4xx or 5xx:

```typescript theme={null}
import { ofetch } from 'ofetch'

try {
  const data = await ofetch('/api/user/999')
} catch (error) {
  console.error(error)
  // FetchError: [GET] "/api/user/999": 404 Not Found
}
```

This eliminates the need to manually check `response.ok` after every request.

## FetchError Type

When a request fails, ofetch throws a `FetchError` with detailed information:

```typescript theme={null}
import { ofetch, FetchError } from 'ofetch'

try {
  await ofetch('/api/protected', {
    method: 'POST',
    body: { name: 'test' }
  })
} catch (error) {
  if (error instanceof FetchError) {
    console.log(error.message)      // [POST] "/api/protected": 403 Forbidden
    console.log(error.status)       // 403
    console.log(error.statusCode)   // 403 (alias)
    console.log(error.statusText)   // "Forbidden"
    console.log(error.statusMessage)// "Forbidden" (alias)
    console.log(error.request)      // Request object or URL string
    console.log(error.response)     // Response object
    console.log(error.data)         // Parsed response body
    console.log(error.options)      // Request options used
  }
}
```

### FetchError Properties

<ParamField path="message" type="string">
  Formatted error message in the format: `[METHOD] "url": status statusText errorMessage`

  Example: `[GET] "/api/user": 404 Not Found`
</ParamField>

<ParamField path="status" type="number | undefined">
  HTTP status code of the response (e.g., 404, 500)
</ParamField>

<ParamField path="statusCode" type="number | undefined">
  Alias for `status`
</ParamField>

<ParamField path="statusText" type="string | undefined">
  HTTP status text (e.g., "Not Found", "Internal Server Error")
</ParamField>

<ParamField path="statusMessage" type="string | undefined">
  Alias for `statusText`
</ParamField>

<ParamField path="data" type="any">
  The parsed response body, same as `response._data`. This is particularly useful for API errors that return error details in the response body.
</ParamField>

<ParamField path="request" type="FetchRequest">
  The request URL string or Request object that was used
</ParamField>

<ParamField path="response" type="FetchResponse | undefined">
  The Response object with the parsed data available as `_data` property
</ParamField>

<ParamField path="options" type="FetchOptions">
  The resolved request options that were used
</ParamField>

## Accessing Error Data

The `error.data` property contains the parsed response body, which is useful for API errors:

```typescript theme={null}
import { ofetch } from 'ofetch'

try {
  await ofetch('/api/users', {
    method: 'POST',
    body: { email: 'invalid-email' }
  })
} catch (error) {
  // Access structured error information from the API
  console.log(error.data)
  // {
  //   status: 400,
  //   message: "Validation failed",
  //   errors: {
  //     email: "Invalid email format"
  //   }
  // }
  
  // Display user-friendly error message
  if (error.data?.errors) {
    for (const [field, message] of Object.entries(error.data.errors)) {
      console.error(`${field}: ${message}`)
    }
  }
}
```

<Note>
  The `error.data` property is the same as `error.response._data`, providing convenient access to the parsed response body.
</Note>

## Ignoring Response Errors

You can disable automatic error throwing using the `ignoreResponseError` option:

<ParamField path="ignoreResponseError" type="boolean" default="false">
  When set to `true`, ofetch will not throw errors for 4xx and 5xx responses. Instead, it returns the response normally.
</ParamField>

```typescript theme={null}
import { ofetch } from 'ofetch'

// Returns response object instead of throwing
const response = await ofetch('/api/resource', {
  ignoreResponseError: true
})

if (response.status === 404) {
  console.log('Resource not found')
} else if (response.status >= 500) {
  console.log('Server error')
}
```

This is useful when you need to handle different status codes explicitly:

```typescript theme={null}
const response = await ofetch('/api/check', {
  ignoreResponseError: true
})

switch (response.status) {
  case 200:
    console.log('Success:', response._data)
    break
  case 404:
    console.log('Not found')
    break
  case 403:
    console.log('Forbidden')
    break
  default:
    console.log('Other status:', response.status)
}
```

## Error Status Codes

ofetch throws errors for all status codes between 400 and 599 (inclusive):

* **4xx Client Errors**: 400-499 (Bad Request, Unauthorized, Forbidden, Not Found, etc.)
* **5xx Server Errors**: 500-599 (Internal Server Error, Bad Gateway, Service Unavailable, etc.)

## Error Cause

When the underlying fetch operation fails (network error, timeout, etc.), the original error is preserved in the `cause` property:

```typescript theme={null}
try {
  await ofetch('https://invalid-domain.example.com')
} catch (error) {
  console.log(error.cause) // Original network error
}
```

<Tip>
  ofetch polyfills the `cause` property for runtimes that don't support it natively.
</Tip>

## TypeScript Error Handling

You can type the error data for better TypeScript support:

```typescript theme={null}
import { ofetch, FetchError } from 'ofetch'

interface ApiError {
  message: string
  code: string
  errors?: Record<string, string>
}

try {
  await ofetch('/api/users', { method: 'POST', body: {} })
} catch (error) {
  if (error instanceof FetchError<ApiError>) {
    // error.data is now typed as ApiError
    console.log(error.data?.message)
    console.log(error.data?.code)
  }
}
```
