id: foo
type: defaultError Handlers
Error handlers kick in when any of the stages of the regular rule pipeline fail and let you define logic to handle such situations. This page describes the available error handler types in detail.
Some of the error handlers may support or require additional configuration. The corresponding properties are annotated with mandatory, respectively optional to denote configuration requirement, as well as with overridable, not overridable and partially overridable to indicate whether the property can be overridden in a rule pipeline.
Default
This error handler is always there and is executed if no other error handler mechanism is responsible for the error. Actually, there is no need to explicitly configure it. The only exception is to allow overriding the default rule’s error handler chain in a specific rule for performance reasons (if configured error handlers in the default rule should not be considered). This mechanism type doesn’t have any configuration options.
To enable the usage of this mechanism, you have to set the type property to default.
Generic
This error handler mechanism allows defining fully custom HTTP error responses (status code, headers, and body). It is useful for protocol-specific error semantics, e.g. JSON-RPC style payloads.
To enable the usage of this mechanism, you have to set the type property to generic.
Configuration is mandatory by making use of the config property supporting the following settings:
code: int (mandatory, overridable)The HTTP status code to return. Allowed range:
100to599.headers: array[object] (optional, overridable)List of header entries. Each entry must contain exactly one
name: valuepair. The header values can be templated and have access to theRequestobject and configuredValues.Use multiple list entries with the same header name if you need repeated headers. body: string (optional, overridable)Optional response body template with access to the
Requestobject and configuredValues.values: map[string]string (optional, partially overridable)Template values available as
Values.
The configuration below lets heimdall respond with a fixed HTTP 400 Bad Request and a small JSON body.
id: bad_request
type: generic
config:
code: 400
headers:
- Content-Type: application/json
body: '{"error": "bad request"}'The generic error handler below responds with HTTP 302 Found and sets Location to https://127.0.0.1:4433/self-service/login/browser with the return_to query parameter set to the URL encoded value of the current URL.
So, e.g. if heimdall handles a request for https://my-service.local/foo and this handler is selected by the error pipeline, the HTTP response will have code 302 Found and Location set to https://127.0.0.1:4433/self-service/login/browser?return_to=https%3A%2F%2Fmy-service.local%2Ffoo.
id: redirect
type: generic
config:
code: 302
headers:
- Location: https://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }}To execute this error handler, reference it in the error pipeline of your rule. The optional if clause defines under which conditions it is applied. In the example below, browser-based authentication failures are addressed:
on_error:
- if: type(Error) == authentication_error && Request.Header("Accept").contains("text/html")
error_handler: redirectIf the error handler defined below kicks in, heimdall will respond with HTTP 401 Unauthorized and a WWW-Authenticate header set to Basic realm="My fancy app".
id: basic_auth_like
type: generic
config:
code: 401
headers:
- WWW-Authenticate: Basic realm="My fancy app"The example below is shown for an MCP gateway scenario and emits a JSON-RPC error payload. For A2A gateway scenarios, the configuration is more or less identical; in most cases only protocol-specific error codes/messages need to be adjusted.
id: mcp_error
type: generic
config:
code: 200
headers:
- Content-Type: application/json
body: |
{
"jsonrpc": "2.0",
"id": {{ .Request.Body.id | toJson }},
"error": {
"code": {{ .Values.errorCode }},
"message": {{ .Values.message | quote }}
}
}
values:
errorCode: -32603
message: "internal error"In your rule, you would then use it like this:
on_error:
- if: type(Error) == authentication_error
error_handler: mcp_error
config:
values:
errorCode: -32001
message: unauthorizedRedirect
This error handler mechanism allows redirecting the client to another endpoint, e.g. to let the user authenticate. Technically this error handler returns e.g. a HTTP 302 Found response code and sets the HTTP Location header.
The Equivalent configuration using |
To enable the usage of this mechanism, you have to set the type property to redirect.
Configuration is mandatory by making use of the config property supporting the following settings:
to: URL (mandatory, not overridable)The url to redirect the client to via the
Locationheader. Can be templated and has access to theRequestobject.When creating query parameters by making use of templates, don’t forget to encode the values using the urlencfunction. See also examples below.code: int (optional, not overridable)The code to be used for the redirect. Defaults to
302 Found. Both301 Moved Permanentlyand302 Foundare authorized.
The redirect error handler below returns a redirect to https://127.0.0.1:4433/self-service/login/browser with the return_to query parameter set to the URL encoded value of the current URL.
So, e.g. if heimdall handles a request for https://my-service.local/foo and this handler is selected by the error pipeline, the HTTP response to the client will have the code 302 Found set and the Location header set to https://127.0.0.1:4433/self-service/login/browser?return_to=https%3A%2F%2Fmy-service.local%2Ffoo
id: authenticate_with_kratos
type: redirect
config:
to: https://127.0.0.1:4433/self-service/login/browser?return_to={{ .Request.URL | urlenc }}To execute this error handler, reference it in the error pipeline of your rule. The optional if clause defines under which conditions it is applied, for example for browser-based authentication failures:
on_error:
- if: type(Error) == authentication_error && Request.Header("Accept").contains("text/html")
error_handler: authenticate_with_kratosWWW-Authenticate
This error handler mechanism responds with HTTP 401 Unauthorized and a WWW-Authenticate HTTP header set. By configuring this error handler you can implement the Basic HTTP Authentication Scheme by also making use of the Basic Auth authenticator. Without that authenticator, the usage of this error handler does actually not make any sense.
The Equivalent configuration using |
To enable the usage of this error handler, you have to set the type property to www_authenticate.
Configuration is mandatory by making use of the config property supporting the following settings:
realm: string (optional, overridable)The "realm" according to RFC 7235, section 2.2. Defaults to "Please authenticate".
If the www authenticate error handler below kicks in, heimdall will respond with HTTP 401 Unauthorized and a WWW-Authenticate header set to Basic realm="My fancy app".
id: basic_authenticate
type: www_authenticate
config:
realm: "My fancy app"To execute this error handler, reference it in the error pipeline of your rule. The optional if clause defines under which conditions it is applied:
on_error:
- if: type(Error) == authentication_error
error_handler: basic_authenticateLast updated on Apr 23, 2026