> ## Documentation Index
> Fetch the complete documentation index at: https://tyk.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Customizing Error Responses

> Learn how to customize the HTTP error responses returned by Tyk Gateway to API clients, using Error Overrides, Response Body Overrides, and Authentication Error Configuration

## Availability

| Component                                                  | Version                                                                                  | Edition                |
| :--------------------------------------------------------- | :--------------------------------------------------------------------------------------- | :--------------------- |
| Tyk Gateway (Error Overrides)                              | Available since [v5.13.0](/developer-support/release-notes/gateway#5-13-0-release-notes) | Community & Enterprise |
| Tyk Gateway (Response Body Overrides, `override_messages`) | All versions                                                                             | Community & Enterprise |

<Note>
  This document focuses exclusively on customizing errors returned by API proxies deployed on the Gateway (data plane traffic). It does not apply to errors returned by the Tyk Dashboard API nor the Tyk Gateway API (management traffic).
</Note>

## Tyk Gateway Error Handling

When an error occurs during request processing, Tyk Gateway generates an HTTP error response automatically. Error conditions include authentication failures, rate limit rejections, request validation failures, and upstream connection problems, as well as error status codes (`HTTP 4xx` and `HTTP 5xx`) returned by upstream services.

The default response comprises:

* the HTTP status code defined by the triggering middleware
* a `Content-Type: application/json` header
* an `X-Generator: tyk.io` header
* a JSON response body

```http theme={null}
HTTP/1.1 403 Forbidden
Content-Type: application/json
X-Generator: tyk.io

{"error": "Access to this API has been disallowed"}
```

Notes on the default error response:

* the response is provided in JSON format regardless of the `Content-Type` of the request.
* the `X-Generator` header can be suppressed by setting [`hide_generator_header: true`](/tyk-oss-gateway/configuration#hide_generator_header) in `tyk.conf` (or using the equivalent environment variable).

This default behavior is often insufficient in production for various reasons such as:

* **Standardizing Format:** clients expect a specific error structure, such as [RFC 7807 Problem Details](https://datatracker.ietf.org/doc/html/rfc7807), that the default response does not produce.
* **Gateway Migration:** clients may depend on error response formats from a previous API gateway that differ from Tyk's defaults.
* **Hiding Internal Detail:** default messages might expose information about your authentication mechanism, key structure, or upstream topology.
* **Consistency Across APIs:** upstream services may return different error formats; normalizing them at the Gateway improves the client experience.
* **Per-API Requirements:** different APIs published on the same Gateway may need to return different error formats or status codes for the same underlying error condition.

### Customization Mechanisms

Tyk provides three mechanisms for customizing error responses. The first two are long-standing features with narrow, specific purposes. The third, introduced in Tyk v5.13.0, is a comprehensive replacement for both.

[**Authentication Error Configuration**](#authentication-error-configuration) targets specific scenarios: the HTTP status codes and message strings that Tyk returns for errors reported by the [client authentication](/api-management/client-authentication) middleware, which may not suit your API contract. Its scope is intentionally narrow: it covers only the 11 built-in auth and OAuth error conditions and applies identically to all APIs on the Gateway.

[**Response Body Overrides**](#response-body-overrides) solve a different problem: the format of the response body. By placing Go template files in the Gateway's `templates/` directory, you can replace the body structure (as JSON or XML) for any HTTP error status code. Templates are resolved globally based on status code and the request's `Content-Type`. This applies identically to all APIs; it cannot intercept or modify error responses that originated from upstream services, and cannot differentiate between different errors that generate the same status code.

[**Error Overrides**](#error-overrides), introduced in Tyk v5.13.0, supersedes both. You define a set of rules against which each error is tested. Separate rules can be configured for different status codes, error type, message pattern, or upstream response content. When a rule matches, Tyk can modify any part of the response before it is returned to the client. Error Overrides works with errors generated by both Tyk and upstream services, which neither legacy mechanism can intercept.

The table below summarizes the key differences:

|                           | Authentication Error Configuration |     Response Body Overrides    |          Error Overrides         |
| ------------------------- | :--------------------------------: | :----------------------------: | :------------------------------: |
| Available since           |           Early versions           |              v2.2              |              v5.13.0             |
| Configuration location    |             `tyk.conf`             | Template files in `templates/` | `tyk.conf` and/or API definition |
| Scope                     |              All APIs              |            All APIs            |        All APIs or per-API       |
| Customize status code     |                  ✅                 |                ❌               |                 ✅                |
| Customize message string  |                  ✅                 |                ❌               |                 ✅                |
| Customize body format     |                  ❌                 |                ✅               |                 ✅                |
| Customize upstream errors |                  ❌                 |                ❌               |                 ✅                |
| Customize by error type   |                  ❌                 |                ❌               |                 ✅                |

For new API deployments, we strongly recommend that you use **Error Overrides** to customize error responses. Authentication Error Configuration and Response Body Overrides remain fully supported for backward compatibility.

### How the Mechanisms Interact

The three error customization mechanisms can be implemented together. **We don't recommend this**, now that Error Overrides provides full customization, however it is important to understand how they will interact if more than one is deployed.

{/*
Suggested diagram: flowchart with these steps:
1. Gateway starts up -> Authentication Error Configuration remaps default auth/OAuth status codes and messages
2. Request arrives and error occurs
3. Error Overrides evaluated -> if a matching rule provides a complete body, return response immediately (end)
4. If no complete body from Error Overrides -> Response Body Overrides format the body
5. HTTP response sent to client
*/}

* **Authentication Error Configuration runs at Gateway startup, not at request time.** Error Overrides and Response Body Overrides see the already-modified status codes and messages, not the original Tyk defaults.
* **Error Overrides only bypasses Response Body Overrides when it provides a complete body.** A rule that changes only the status code or message still falls through to the template for body formatting.
* **The mechanisms can coexist.** Error Overrides can be introduced incrementally: existing template files and `override_messages` settings continue to function for any error condition not covered by an override rule.

## Error Overrides

Error Overrides is a powerful, declarative system that allows you to intercept errors and rewrite their HTTP status codes, headers, and bodies. It can handle both Gateway-generated errors (e.g., rate limits, auth failures) and Upstream errors (e.g., `HTTP 500 Internal Server Error` returned from your backend service).

It works using a rule matching approach where each error response generated by Tyk middleware (including the proxy stage which receives the response from the upstream) is checked against a set of [rules](#rule-structure) that determine the [modification](#response-customization) to be made to matching responses. If no rule matches, the response is returned to the client unaltered.

### Rule Structure

Rules are organized by status code key, which can be either an exact code such as `400` or a wildcard pattern such as `4xx` or `5xx`. Multiple rules can share the same key; they are evaluated in order and the first match wins.

Each rule has two objects:

* an optional `match` object to specify which errors within that status code trigger the rule.
* a `response` object that defines what Tyk returns when the rule fires (in place of the original error response).

Omitting `match` means that the transformation in the `response` is applied to **any error with that status code**.

```json theme={null}
{
  "error_overrides": {
    "403": [                        // key: exact code ("403") or wildcard ("4xx")
      {
        "match": {                  // optional: specifies which errors trigger this rule
          "flag": "AKI"             // match by error classification flag
        },
        "response": {               // what Tyk returns when this rule fires
          "status_code": 401,       // new HTTP status code
          "headers": { "WWW-Authenticate": "Bearer" },        // headers to set in the response
          "body": "{\"error\": \"Authentication required\"}"  // response body
        }
      }
    ]
  }
}
```

This structure is used for [Gateway-level](#gateway-level) overrides; for API-level overrides see the [relevant section](#api-level).

### Matching Criteria

After the initial match on the status code key, you can refine which errors trigger the rule using the `match` object. The fields available depend on whether the error was generated by Tyk Gateway or returned by an upstream service.

| Field                     | Gateway-generated errors                                     | Upstream errors                                                                                                     |
| ------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
| `flag`                    | Matches any flag from the [Flag Reference](#flag-reference). | `URS` is supported for `5xx` errors; leave blank for `4xx` errors. Any other value prevents the rule from matching. |
| `messagePattern`          | Regex matched against the error message string.              | Regex matched against the response body.                                                                            |
| `bodyField` + `bodyValue` | Not evaluated.                                               | A [gjson](https://github.com/tidwall/gjson) path and expected value matched against a JSON response body.           |

#### Matching Gateway-generated errors

* If `flag` is set and matches, the rule fires.
* Otherwise, if `messagePattern` is set and matches the error message, the rule fires.
* If a match field is set but does not match, the rule does not fire.
* If **neither** field is set, the rule **matches any error with that status code**.

#### Matching Upstream-generated errors

`bodyField` and `bodyValue` work together to match a specific field and value in the upstream JSON response body. `bodyField` is a [gjson](https://github.com/tidwall/gjson) path expression identifying a field in the response; `bodyValue` is the expected string value for that field.

For example, given an upstream error response:

```http theme={null}
HTTP/1.1 503 Service Unavailable
Content-Type: application/json

{"error": {"code": "OUT_OF_STOCK"}}
```

The following match configuration fires only when the upstream returns that specific error code:

```json theme={null}
"match": {
  "flag": "URS",
  "bodyField": "error.code",
  "bodyValue": "OUT_OF_STOCK"
}
```

**`5xx` Upstream Errors:**

* Set `flag=URS` to match upstream `5xx` responses only, excluding Gateway-generated errors with the same code (such as a circuit-breaker `503`).
* To differentiate between different upstream `5xx` errors, set `bodyField`/`bodyValue` or `messagePattern` to match on the response body. Note that `messagePattern` matches on the response body for upstream errors.

**`4xx` Upstream Errors:**

* `flag=URS` is `5xx`-only. There is no flag that isolates upstream `4xx` responses from Gateway-generated ones with the same status code.
* Use `messagePattern` to differentiate by content: for Gateway errors it matches against the error message string; for upstream errors it matches against the response body. A pattern that matches the upstream response format but not Tyk's fixed error messages effectively targets upstream responses only.

<Warning>
  `bodyField`/`bodyValue` is not evaluated when matching Gateway-generated errors. A `4xx` rule that sets only body criteria, with no `flag` or `messagePattern`, will match all Gateway-generated errors of that status code, not just upstream responses.
</Warning>

<Note>
  When `messagePattern` or `bodyField`/`bodyValue` are used to match upstream responses, Tyk reads up to 4 KB of the response body. Content beyond 4 KB is not evaluated. If no match is found, the original response body is passed through unchanged.
</Note>

### Response Customization

The response object defines what Tyk returns to the client when a rule matches (or fires). *All fields are optional*: provide any combination to achieve the override you need.

**`statusCode`**: (`status_code` in Tyk Classic and `tyk.conf`)

* This is the HTTP status code to return to the client.
* Any valid HTTP status code is accepted.
* If omitted, the original error status code is preserved.
* Available as `{{.statusCode}}` in [Go Template Syntax](#go-template-syntax) used in `body` or `template`.

**`headers`**:

* A JSON object of key-value string pairs to set on the response. These are merged into the existing response headers; any key you specify sets or overrides that header while all other headers remain intact.
* If omitted, no additional headers are set.
* To remove a header, include it in `headers` with an empty value.
* Note that the `X-Generator` header cannot be removed via override rules; suppress it globally using [`hide_generator_header`](/tyk-oss-gateway/configuration#hide_generator_header).

**`message`**:

* The error message text.
* Available as `{{.Message}}` in [Go Template Syntax](#go-template-syntax) used in `body` or `template`.
* If omitted, `{{.Message}}` resolves to an empty string in the `body` or `template`.

**`body`**:

* The response body, written verbatim to the client.
* Can be a static string or a Go template string (see [Go Template Syntax](#go-template-syntax)).
* When `body` is provided, the legacy template system is bypassed entirely.
* If `body` is set, `template` is ignored.

**`template`**:

* The base filename (without extension) of a file in the Gateway's `templates/` directory.
* The file content is used as the response body, written verbatim to the client.
* Tyk appends `.json` or `.xml` to the base filename based on the `Content-Type` of the original request.
  * For example, `"my_error"` resolves to `templates/my_error.json` for JSON requests and `templates/my_error.xml` for XML requests.
* Use `template` as an alternative to `body` when the template body is large or shared across multiple rules.

#### Partial Override

If neither `body` nor `template` is set, the rule is a partial override as it does not contain any response body content. Tyk applies the `statusCode` and `message` from the matching rule. Use this when you want to change the status code or message while retaining the existing body format.

<Note>
  A partial override will pass through the legacy template system, which may format the response body. Be careful if you have both Error Overrides and [Response Body Overrides](#response-body-overrides) configured to avoid unintended behavior.
</Note>

#### XML Clients

Inline `body` overrides are written verbatim **regardless of the `Content-Type` of the original request**. To serve XML to XML clients using an inline body, ensure that the `body` contains XML formatted content. If using `template`, then ensure you provide a `.xml` file variant, as Tyk will select that given `Content-Type: "application/xml"` in the request.

#### Go Template Syntax

<Note>
  The files referenced by the `template` field are distinct from the [Response Body Overrides](#response-body-overrides) legacy system. Both reside in the Gateway's `templates/` directory, but Error Override template files are referenced explicitly by name in a rule and have access to the variables listed below. Legacy template files are selected automatically by filename convention and only have access to `{{.Message}}`.
</Note>

The `body` field and the files referenced by the `template` field support [Go template syntax](/api-management/traffic-transformation/go-templates). The variables available in error override templates are specific to the error context and are listed below.

The following variables are always available:

* `{{.StatusCode}}`: The HTTP status code being returned.
* `{{.Message}}`: The error message text.

Note that for both variables, if `response.statusCode` or `response.message` are declared in the override rule, these will be applied prior to the template being resolved and so the override value will be applied to the template, not the value from the original error message.

Some errors inject additional variables:

* `{{.InvalidParams}}`: A string describing the specific validation failure. Only available when `flag=BIV` (see [Request Validation](/api-management/traffic-transformation/request-validation)). Example: `"body.age must be a positive integer"`.

Example of an RFC 7807 compliant inline template:

```json theme={null}
"response": {
  "statusCode": 400,
  "headers": { "Content-Type": "application/problem+json" },
  "body": "{\"type\": \"https://example.com/probs/validation\", \"title\": \"Invalid Request\", \"status\": {{.StatusCode}}, \"detail\": \"{{.Message}}\"}"
}
```

### Configuration

Error Overrides can be configured in two layers:

* [Gateway-level](#gateway-level) configuration is applied to all APIs deployed on the Gateway
* [API-level](#api-level) configuration applies to a specific API and is evaluated first

If no API-level rule matches, Tyk checks the error response against the Gateway-level rules.

#### Gateway Level

Configure overrides that apply to all APIs deployed on the Gateway using the [`error_overrides`](/tyk-oss-gateway/configuration#error_overrides) object in the Gateway config (`tyk.conf` or equivalent environment variables):

```json theme={null}
"error_overrides": {
  "403": [{
    "match": {
      "flag": "AKI"
    },
    "response": {
      "status_code": 401,
      "headers": { "WWW-Authenticate": "Bearer" },
      "body": "{\"error\": \"Authentication required\"}"
    }
  }]
}
```

#### API Level

Configure overrides for a specific API in the [`errorOverrides`](/api-management/gateway-config-tyk-oas#erroroverrides) section of the Tyk Vendor Extension:

```json theme={null}
"x-tyk-api-gateway": {
  "errorOverrides": {
    "enabled": true,
    "value": {
      "403": [{
        "match": {
          "flag": "AKI"
        },
        "response": {
          "statusCode": 401,
          "headers": { "WWW-Authenticate": "Bearer" },
          "body": "{\"error\": \"Authentication required\"}"
        }
      }]
    }
  }
}
```

Set `"enabled": false` to disable API-level overrides without removing the configuration.

If using Tyk Classic APIs, configure overrides at the top level of the API definition:

```json theme={null}
{
  "error_overrides_disabled": false,
  "error_overrides": {
    "403": [{
      "match": {
        "flag": "AKI"
      },
      "response": {
        "status_code": 401,
        "headers": { "WWW-Authenticate": "Bearer" },
        "body": "{\"error\": \"Authentication required\"}"
      }
    }]
  }
}
```

Set `"error_overrides_disabled": true` to disable API-level overrides without removing the configuration.

### Flag Reference

The following flags classify errors generated by Tyk Gateway and can be used in the `flag` field of a match object. For intercepting upstream error responses, see [Upstream Error Responses](#upstream-error-responses).

#### Authentication and Authorization Errors

|  Flag | Description                              |         Typical HTTP Status        |
| :---: | ---------------------------------------- | :--------------------------------: |
| `AMF` | Authorization field missing from request | `401` (auth token) / `400` (OAuth) |
| `AKI` | API key invalid                          |                `403`               |
| `TKE` | Token or certificate has expired         |                `403`               |
| `TKI` | Token is invalid                         |                `403`               |
| `TCV` | Token claims invalid (JWT)               |                `401`               |
| `EAD` | External authentication denied           |                `403`               |
| `CRQ` | Mutual TLS client certificate required   |                `401`               |
| `CMM` | Mutual TLS client certificate mismatch   |                `401`               |

#### Request Validation Errors

|  Flag | Description                                                                            | Typical HTTP Status |
| :---: | -------------------------------------------------------------------------------------- | :-----------------: |
| `BTL` | Request body too large                                                                 |        `400`        |
| `CLM` | Content-Length header missing                                                          |        `411`        |
| `BIV` | [Request validation](/api-management/traffic-transformation/request-validation) failed |    `400` or `422`   |
| `IHD` | Invalid request header                                                                 |        `400`        |

#### Rate Limiting and Quota Errors

|  Flag | Description          | Typical HTTP Status |
| :---: | -------------------- | :-----------------: |
| `RLT` | Request rate limited |        `429`        |
| `QEX` | Quota exceeded       |        `403`        |

#### Upstream Connectivity Errors

|  Flag | Description                                               | Typical HTTP Status |
| :---: | --------------------------------------------------------- | :-----------------: |
| `UCF` | Upstream connection refused                               |        `500`        |
| `UCT` | Upstream connection timed out (TCP connect phase)         |        `500`        |
| `URR` | Upstream connection reset by peer                         |        `500`        |
| `URT` | Upstream request timed out (no response headers received) |        `504`        |
| `EPI` | Broken pipe (EPIPE) writing to upstream                   |        `500`        |
| `CAB` | Connection aborted                                        |        `500`        |
| `NRS` | Network reset (ENETRESET)                                 |        `500`        |
| `DNS` | DNS resolution failure                                    |        `500`        |
| `NRH` | No route to host                                          |        `500`        |
| `NHU` | No healthy upstreams available                            |        `503`        |
| `CBO` | Circuit breaker open                                      |        `503`        |
| `CDC` | Client disconnected before response was sent              |        `499`        |
| `UPE` | Upstream protocol error (generic fallback)                |        `500`        |

#### TLS Errors

|  Flag | Description                                     | Typical HTTP Status |
| :---: | ----------------------------------------------- | :-----------------: |
| `TLE` | TLS certificate on the upstream has expired     |        `500`        |
| `TLI` | TLS certificate on the upstream is invalid      |        `500`        |
| `TLM` | TLS certificate hostname mismatch               |        `500`        |
| `TLN` | TLS certificate not trusted (unknown authority) |        `500`        |
| `TLH` | TLS handshake failed                            |        `500`        |
| `TLP` | TLS protocol error                              |        `500`        |
| `TLA` | TLS alert (handshake failure, version mismatch) |        `500`        |
| `TLC` | TLS certificate chain incomplete                |        `500`        |

#### Upstream Error Responses

Upstream `5xx` error responses carry the `URS` flag. Use `flag=URS` in a match rule to restrict it to upstream responses only, preventing it from also matching gateway-generated errors with the same status code.

|  Flag | Description                            |  Typical HTTP Status |
| :---: | -------------------------------------- | :------------------: |
| `URS` | Upstream returned a 5xx error response | Varies (`500`–`599`) |

## Response Body Overrides

<Note>
  This is a legacy feature. For new implementations, we recommend using [Error Overrides](#error-overrides) instead.
</Note>

The Response Body Overrides system works by the Gateway reading text files from the `templates/` directory in its local filesystem. Tyk selects a file based on the HTTP status code and the request's `Content-Type` (for example, `error_500.json` or `error_500.xml`), falling back to a generic `error.json` or `error.xml` if no status code-specific file exists.

The content of the selected file is used to replace the body of the error response. Go template syntax is available, but only the `{{.Message}}` variable is supported, which contains the error message text.

Note the following limitations on the scope of this feature:

* **Gateway-Level Scope:** The same customized response bodies are applied for all APIs on the Gateway.
* **Upstream Errors:** This method cannot intercept upstream errors.
* **Status Code Scope:** There is no way to differentiate between different errors that share the same status code.
* **`HTTP 404` Limitation:** Response Body Overrides cannot be used to customize the body of `HTTP 404` responses.
* **Response Body Only:** This method does not enable customization of status code, error message or headers.

<Warning>
  The files used by Response Body Overrides share the same `templates/` directory as the files referenced by the Error Overrides [`template`](#go-template-syntax) field. If using both override methods, be careful to take account of the specific naming required by Response Body Overrides and the fact that this cannot be disabled, so a file named `error.json` will be used to override any error response without a specific [rule](#rule-structure).
</Warning>

## Authentication Error Configuration

<Note>
  This is a legacy feature. For new implementations, we recommend using [Error Overrides](#error-overrides) instead.
</Note>

Authentication Error Configuration allows you to change the default HTTP status codes and error messages that Tyk returns for its built-in authentication and OAuth error conditions, using the `override_messages` configuration in `tyk.conf`. It is provided for cases where your API contract requires specific status codes or messages for auth failures that differ from Tyk's defaults.

Specify the message ID in the `override_messages` object in `tyk.conf` and provide a `code`, `message`, or both:

```json theme={null}
"override_messages": {
  "auth.key_not_found": {
    "code": 401,
    "message": "Invalid or missing API key"
  }
}
```

Note the following limitations on the scope of this feature:

* **Limited Scope:** This method only works for specific auth-related errors.
* **Gateway-Level Scope:** The same responses are applied for all APIs on the Gateway.
* **Limited Customization:** This method does not enable customization of response body or headers.

<Warning>
  Authentication Error Configuration takes effect at Gateway startup, before any requests are processed. If configured alongside Error Overrides, the Error Overrides rules see the values modified by Authentication Error Configuration, not the original Tyk defaults. For example, if you use `override_messages` to remap an error to a different status code, any Error Overrides rules must match the new code, not the original.
</Warning>

**Supported Message IDs and Their Defaults:**

| Message ID                   | Default Message                                       | Default HTTP Status |
| ---------------------------- | ----------------------------------------------------- | :-----------------: |
| `auth.auth_field_missing`    | "Authorization field missing"                         |        `401`        |
| `auth.key_not_found`         | "Access to this API has been disallowed"              |        `403`        |
| `auth.cert_not_found`        | "Access to this API has been disallowed"              |        `403`        |
| `auth.key_is_invalid`        | "Access to this API has been disallowed"              |        `403`        |
| `auth.cert_expired`          | "Certificate has expired"                             |        `403`        |
| `auth.cert_required`         | "Client certificate required"                         |        `401`        |
| `auth.cert_mismatch`         | "Access to this API has been disallowed"              |        `401`        |
| `oauth.auth_field_missing`   | "Authorization field missing"                         |        `400`        |
| `oauth.auth_field_malformed` | "Bearer token malformed"                              |        `400`        |
| `oauth.key_not_found`        | "Key not authorised"                                  |        `403`        |
| `oauth.client_deleted`       | "Key not authorised. OAuth client access was revoked" |        `403`        |

## Other Error Configurations

Tyk offers error configurations within certain middleware:

* [**Request Validation**](/api-management/traffic-transformation/request-validation#configuring-the-request-validation-middleware): When using Request Validation middleware, the HTTP status code returned in case of validation failure can be configured in the API definition.
* [**HMAC Signature Validation**](/basic-config-and-security/security/authentication-authorization/hmac-signatures): The HMAC signature authentication middleware exposes fields that set the HTTP status code and error message returned when signature validation fails.
* **Custom Plugins**: [JavaScript plugins](/api-management/plugins/javascript#using-returnoverrides) and [Rich Plugins](/api-management/plugins/rich-plugins#returnoverrides) can use the *Return Overrides* mechanism to halt middleware execution and return a custom HTTP response directly to the client. [Go plugins](/api-management/plugins/golang#terminating-the-request) can write directly to the `http.ResponseWriter` to terminate the request and return a fully custom status code, headers, and body.
* [**Virtual Endpoints**](/api-management/traffic-transformation/virtual-endpoints#working): Virtual endpoints execute a JavaScript function that returns a fully custom response (status code, headers, and body) via the `TykJsResponse()` function.
