Error Handling with Connectors
Mapping responses for non-200 HTTP responses
Learn how Connectors handle errors by default and how you can customize error handling.
Default behavior
When an HTTP endpoint returns a non-200 status, GraphOS Router includes errors in the GraphQL errors
array of the response. It uses the following default error structure:
{
"data": null,
"errors": [
{
"message": "Request failed",
"path": ["products"],
"extensions": {
"http": {
"status": 500
},
"connector": {
"coordinate": "ecomm:Query.products@connect[0]"
},
"code": "CONNECTOR_FETCH",
"service": "ecomm"
}
}
]
}
Fields that return non-200 HTTP responses are set to null
in the response's data
attribute, following the GraphQL specification.
Error handling customization
You can customize errors in the response using the errors
property on @source
or @connect
directives.
The errors
property lets you customize the message
and extensions
fields in errors
objects in the GraphQL response using information from the HTTP response and literal values.
{
"data": null,
"errors": [
{
"message": "Custom message",
"path": ["products"],
"extensions": {
"http": {
"customField": "Custom value"
},
/// ...
}
}
]
}
The errors.message
and errors.extensions
fields take mapping expressions, which are applied on the response body, just like selection mapping.
You can access all of the mapping language's variables and methods in these fields.
Customizing errors.message
You can set a custom error message using the errors.message
property on @connect
and @source
directives.
For example, this schema:
type Query {
users: [User]
@connect(
http: { GET: "http://my-api.com/users" }
selection: "id name"
errors: {
message: "error.message"
}
)
}
results in a GraphQL response with a customized errors.message
:
{
"data": null,
"errors": [
{
"message": "There was a critical failure!",
"path": ["users"],
/// ...
}
]
}
The errors.message
property expects a mapping expression that results in a string.
Valid error.message
mapping expressions
The following are examples of valid mapping expressions for errors.message
:
Using a static literal value:
GraphQL@connect( # --snip -- errors: { message: "$('This is a hard-coded literal message')" } )
Using a response field (in particular,
error.message
)`:GraphQL@connect( # --snip -- errors: { message: "error.message" } )
Using a header value from the response with the
$response.headers
variable:GraphQL@connect( # --snip -- errors: { message: "$response.headers.errorheader->first" } )
Invalid error.message
mapping expressions
The following are examples of invalid mapping expressions for errors.message
:
Using a value that doesn't result in a string, for example, using the
$status
variable, which returns a number:GraphQL❌ Invalid example@connect( # --snip -- errors: { message: "$status" } )
Using an object format:
GraphQL❌ Invalid example@connect( # --snip -- errors: { message: "myProperty: error.message" } )
error.message
precedence rules
If both @source
and @connect
set errors.message
, the @connect
's value takes precedence.
Customizing errors.extensions
You can set custom error extensions using the errors.extensions
property on @connect
and @source
directives.
type Query {
users: [User]
@connect(
http: { GET: "http://my-api.com/users" }
selection: "id name"
errors: {
extensions: """
code: error.code
status: $status
"""
}
)
}
This customization sets additional properties in the GraphQL errors.extensions
object:
{
"data": null,
"errors": [
{
"message": "Request failed",
"path": ["users"],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"status": 500,
"http": {
"status": 500
},
"connector": {
"coordinate": "connector-graph:Query.users@connect[0]"
}
}
}
]
}
The errors.extensions
property expects a mapping expression that results in an object.
Valid errors.extensions
mapping expressions
The following are examples of valid mapping expressions for errors.extensions
:
Using properties from the response:
GraphQL@connect( # --snip -- errors: { extensions: """ code: error.code """ } )
Using the
$status
variable:GraphQL@connect( # --snip -- errors: { extensions: """ status: $status """ } )
Using literal values in a nested structure:
GraphQL@connect( # --snip -- errors: { extensions: """ http: { myField: $("literal Value") } """ } )
Combining multiple properties from different sources:
GraphQL@connect( # --snip -- errors: { extensions: """ code: error.code statusCode: $status errorDetails: { message: error.message timestamp: $response.headers."x-error-timestamp"->first source: $("backend-service") } """ } )
Invalid errors.extensions
mapping expressions
The following example is invalid because it uses a value that doesn't result in an object:
@connect(
# --snip --
errors: {
extensions: "$status"
}
)
errors.extensions
precedence rules
If both @source
and the @connect
set errors.extensions
properties, the response contains both. The extensions
object also retains its default properties. When properties are found in more than one of the three:
Properties set in
@source
overwrite default propertiesProperties set in
@connect
overwrite@source
properties
Additional resources
Refer the mapping language documentation for more information on writing mapping expressions.
See the common errors section on the troubleshooting page for information on composition errors.