Errors (#193)
Errors are a critical part of a consumer's experience when interacting with our APIs. Something isn't working, and it is likely that the user is frustrated. With that in mind, we aim to provide as much information about how to resolve the issue at hand as possible in the error response.
By providing a consistent error format, we allow developers to handle any errors they may receive using common error-handling logic.
Guidance
HTTP APIs at Kong must return errors that adhere to RFC 7807 "Problem Details for HTTP APIs".
The only exception is when there is an infrastructure failure and an application cannot be reached. Third party tools may use their own error format, but should be configured to follow RFC 7807 where possible.
HTTP Content-Type
All error responses must send the application/problem+json
content type
Response Body Fields
All error messages must contain the following fields:
Name |
Required |
Description |
Example |
type |
true |
A unique identifier for this error. When dereferenced it must provide human-readable documentation for the problem. The URL must follow #122 - Resource Names and must not contain URI fragments type |
https://kongapi.info/konnect/invalid-permissions |
status |
true |
The HTTP status code of the error. Useful when passing the response body to child properties in a frontend UI. Must be returned as an integer |
403 |
title |
true |
A short, human-readable summary of the problem. It should not change between occurences of a problem, except for localization. Should be provided as "Sentence case" for direct use in the UI |
Invalid Permissions |
detail |
true |
A human readable explanation specific to this occurence of the problem. This field may contain request/entity data to help the user understand what went wrong. Enclose variable values in square brackets. Should be provided as "Sentence case" for direct use in the UI |
You must have the [administrator] role to perform this action |
instance |
true |
Used to return the correlation ID back to the user, in the format kong:trace:<correlation_id> . This helps us find the relevant logs when a customer reports an issue |
kong:trace:6c1ef33ae5bce33634d7d7d695c7f203 |
|
|
|
|
Here's a complete example:
{
"type": "https://kongapi.info/konnect/invalid-permissions",
"status": 403,
"title": "Invalid Permissions",
"detail": "You must have the [administrator] role to perform this action",
"instance": "kong:trace:6c1ef33ae5bce33634d7d7d695c7f203"
}
Extensions
In addition to the fields shown above, the RFC allows for extensions. Any extensions we choose to use MUST be agreed by the editors.
Invalid Parameters
All 400
errors MUST return an invalid_parameters
key in the response.
Used to indicate which fields have invalid values when validated. Both a human readable value (reason
) and a type that can be used for localised results (rule
) must be provided.
All entries in invalid_parameters
must provide field
, reason
and source
. source
value must be one of : path
, body
, header
, query
.
rule
may be provided as a hint to the consumer to help understand the type of failure. Additional guidance on these fields is given below.
Some rule
types may have additional fields e.g. enum
also has choices
.
The invalid_parameters.reason
field may be taken directly from JSON schema validation e.g. unknown field
or required field missing
.
The invalid_parameters.rule
field can be used by the UI to understand what type of error has been returned.
Example:
{
"type": "https://kongapi.info/konnect/create-member-validation",
"status": 400,
"title": "Validation failed",
"instance": "kong:trace:6c1ef33ae5bce33634d7d7d695c7f203",
"invalid_parameters": [
{ "field": "name", "rule": "required", "reason": "is a required field", "source": "body" },
{
"field": "role",
"reason": "must be one of: [admin, member]",
"rule": "enum",
"choices": ["admin", "member"],
"source": "query",
},
{ "field": "ssh_key", "reason": "invalid SSH key provided", "source": "body" }
]
}
Guidance: field
- For all query parameters that fail validation, the query parameter name must be the
field
value, e.g.:
GET /v1/services/1234?page=-1
= {"field": "page", ...}
- For all request body parameters that fail validation, the
field
value must be a dot notation path to the failing field. If the failing field is in a list, we must provide the failing index:
POST /v1/services
, body: {"service": {"unknown_field": 123}}
= {"field": "service.unknown_field", ...}
POST /v1/services
, body: {"service": {"some_array": [{"unknown_field": 123}]}}
= {"field": "service.some_array[0]", ...}
POST /v1/services
, body: unknown_field=123
= {"field": "unknown_field", ...}
For APIs that do not provide field names (e.g. multipart uploads), you may use field: "body"
to return errors.
It is valid to return multiple entries with the same field (useful for validating against multiple rules).
Guidance: rule
Here are the possible values for rule
, and any additional fields that are required when using each rule:
Rule |
Description |
Additional Fields |
required |
Property is required. |
N/A |
unique |
Value must be unique. |
N/A |
dependent_fields |
Property requires dependent properties to be specified. |
dependents : A list of dependent properties for this field |
enum |
Value must be one of an enumerated set of values. Must be exclusive of min_* , max_* and is_* rules as enum implies the format of a value. |
choices : A list of valid values for this field |
min_length |
String must have a minimum number of characters. |
minimum : Minimum length for this field |
max_length |
String must not exceed a maximum number of characters. |
maximum : Maximum length for this field |
min_items |
Array must contain at least this many items. |
minimum : Minimum items for this field |
max_items |
Array must contain at most this many items. |
maximum : Maximum items for this field |
min |
Numeric field value must be greater than or equal to this value. |
minimum : Minimum numeric value for this field |
max |
Numeric field value must be less than or equal to this value. |
maximum : Maximum numeric value for this field |
min_digits |
Value must have a specified number of digits. |
minimum : Minimum required number of digits |
min_lowercase |
String must have a minimum number of lowercase characters. |
minimum : Minimum required number of lowercase characters |
min_uppercase |
String must have a minimum number of uppercase characters. |
minimum : Minimum required number of upper case characters |
min_symbols |
String must have a minimum number of symbols. |
minimum : Minimum required number of symbols |
is_array |
Value must be an array. |
N/A |
is_boolean |
true or false . |
N/A |
is_date_time |
Value must be a string in RFC-3339 date format. |
N/A |
is_integer |
Value must be a signed integer. |
N/A |
is_null |
Value must be null . |
N/A |
is_number |
Value must be a double precision floating point number. |
N/A |
is_object |
Value must be an object mapping strings to arbitrary types. |
N/A |
is_string |
Value must be a utf-8 string. |
N/A |
is_uuid |
Value must be a UUID. |
N/A |
unknown_property |
Property is not listed in the component definition, and does not allow additional properties. |
N/A |
missing_reference |
The reference represented by the given value doesn't exist. |
N/A |
Any validation rules may be added by raising a PR to update this file. Consult https://swagger.io/docs/specification/data-models/data-types/ when adding new rules.
Base Error Responses
The following table lists "base" or "standard" errors that should be consistent across Konnect APIs. The base path for error type
s is "https://kongapi.info/konnect/". A fully-qualified type
would be "https://kongapi.info/konnect/unauthenticated". The type
minus its base path can be used as an error code, or key for localization.
Type |
Status |
Title |
Detail |
unauthorized |
401 |
Unauthorized |
You must be authenticated to perform this action. |
forbidden |
403 |
Forbidden |
You do not have permission to perform this action. |
quota-exceeded |
403 |
Quota Exceeded |
Maximum number of [entity_type] exceeded. Max allowed: [max]. |
not-found |
404 |
Not Found |
The requested resource was not found. |
invalid-request |
400 |
Invalid Request |
The request is invalid. |
conflict |
409 |
Conflict |
detail varies |
Notes on the above:
quota-exceeded
For enforcing resource quotas in Konnect APIs, the following properties will apply:
- The resource quota applies to a given entity type, e.g. Control Planes (referred to as
[entity_type]
in its detail
string).
- The resource quota will have a non-negative integer value that indicates the allowed maximum aggregate count, or
maximum value, of its given entity type (referred to as
[max]
in its detail string).
not-found
When the resource type is known, detail
may be more specific; for example, "The requested runtime group was not found."
This error must be returned when any of the path parameters in the request are not found. When required query parameters are not found, use the invalid-request
response type.
invalid-request
The detail
field for this error may be more specific.
The invalid_parameters
field is required. If the error cannot be resolved by correcting the issues in the invalid_parameters
field, a new error type should be introduced and documentation written for it.
conflict
Use this error when the requested action is valid but can't be executed due to the current state on the server; for example,
- attempting to insert a record that violates a unique constraint.
The detail
field should describe the conflict and the step(s) to take to resolve it.
If the requested action is not valid, use invalid-request
.
Adding Error Responses
When adding a new error type, consult this AIP to determine if an existing error could be reused. If not, consider whether it is a "base" error or domain-specific. For a base error, raise a PR that adds it to the above section. For domain-specific errors, raise a PR that adds it to the following table.
Validation FAQ
Expected behaviour is not well defined in some error cases. This list documents instances that have been discovered and resolved so far at Kong:
Q: If someone does not have access to a resource, should I return a HTTP 403 or a 404?
A: If the resource is owned by the authenticated user's current organization, return HTTP 403. Otherwise return HTTP 404 to prevent data leakage.
Q: If a parameter in a URL has a type hint (e.g. uuid
, integer
) and a non-valid value is passed, should I return a HTTP 400 or a 404?
A: Return HTTP 404. URLs are opaque identifiers, and the resource at that URL can not exist. Type hints in OpenAPI are hints rather than explicit validation rules. This has been confirmed by the JSON Schema maintainers in the "APIs you won't hate" Slack community.