RFC: HTTP Wire Errors
Overview
This RFC proposes a standardized approach for handling and representing HTTP wire errors in a consistent and structured manner. The goal is to provide clear and detailed error responses that can be easily understood and processed by clients.
Error Response Structure
Each error response will follow a standardized JSON structure with the following fields:
Example
{
"id": "unique-error-id",
"http_error_code": {
"canonical_name": "ERROR_NAME",
"status": 400
},
"message": "short summary of the error",
"detail": "detailed explanation of the error",
"data": {
"additional": "context-specific data"
},
"validation": [
{
"field": "field_name",
"value": "invalid_value",
"reason": "explanation of why the value is invalid"
}
]
}
Canonical Error Names
The following canonical error names are defined:
Error Handling
Invalid Argument
When the client provides an invalid argument, the server should respond with an INVALID_ARGUMENT error.
Example
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"http_error_code": {
"canonical_name": "INVALID_ARGUMENT",
"status": 400
},
"message": "invalid account number provided",
"detail": "the account number '123456789' does not exist in our records"
}
Failed Precondition
When the operation is rejected due to a failed precondition, the server should respond with a FAILED_PRECONDITION error.
Example
{
"id": "b2c3d4e5-f6a7-8901-bcde-f23456789012",
"http_error_code": {
"canonical_name": "FAILED_PRECONDITION",
"status": 400
},
"message": "insufficient funds",
"detail": "the account '987654321' has insufficient funds for the transaction",
"data": {
"current_balance": 50.00,
"required_balance": 100.00
}
}
Unauthenticated
When the request lacks valid authentication credentials, the server should respond with an UNAUTHENTICATED error.
Example
{
"id": "c3d4e5f6-a7b8-9012-cdef-345678901234",
"http_error_code": {
"canonical_name": "UNAUTHENTICATED",
"status": 401
},
"message": "unauthorized access",
"detail": "the provided credentials are invalid"
}
Unauthorized Access
Due to invalid JWK.
{
"id": "b445b036-fd2e-4583-b4cc-61c2b8fb0b73",
"http_error_code": {
"canonical_name": "UNAUTHENTICATED",
"status": 401
},
"message": "auth: verify: jwt: unknown kid"
}
Permission Denied
When the caller does not have permission to execute the specified operation, the server should respond with a PERMISSION_DENIED error.
Example
{
"id": "d4e5f6a7-b8c9-0123-def4-567890123456",
"http_error_code": {
"canonical_name": "PERMISSION_DENIED",
"status": 403
},
"message": "account locked",
"detail": "the account '123456789' is locked due to multiple failed login attempts",
"data": {
"lock_duration": "24 hours"
}
}
Not Found
When the requested resource is not found, the server should respond with a NOT_FOUND error.
Example
{
"id": "e5f6a7b8-c9d0-1234-ef56-789012345678",
"http_error_code": {
"canonical_name": "NOT_FOUND",
"status": 404
},
"message": "transaction not found",
"detail": "the transaction with id 'tx1234567890' was not found"
}
Validation Error
When the request contains invalid fields, the server should respond with an INVALID_ARGUMENT error and include validation details.
Example
{
"id": "c30adf71-25c0-4a2b-a1f2-c3ee17efcd17",
"http_error_code": {
"canonical_name": "INVALID_ARGUMENT",
"status": 400
},
"message": "validation failure",
"detail": "fields were invalid",
"validation": [
{
"field": "name",
"value": "jo",
"reason": "name must be at least 3 characters long"
},
{
"field": "email",
"value": "invalid@comcom",
"reason": "email must be a valid email address"
}
]
}
Internal Server Error
When an unexpected error occurs while processing the request, the server should respond with an INTERNAL error.
{
"id": "f6a7b8c9-d0e1-2345-f678-901234567890",
"http_error_code": {
"canonical_name": "INTERNAL",
"status": 500
},
"message": "server error",
"detail": "an unexpected error occurred while processing the request"
}
Complex Error with Nested Data
When an error involves multiple nested errors, the server should provide detailed context for each part of the error message.
Example
{
"id": "9f8b7c6d-4e5f-4a2b-8c3d-1e2f3a4b5c6d",
"http_error_code": {
"canonical_name": "FAILED_PRECONDITION",
"status": 400
},
"message": "transaction failed: insufficient funds: daily withdrawal limit exceeded",
"data": [
{
"message": "transaction failed",
"data": {
"transaction_id": "tx1234567890",
"amount": 150.00,
"currency": "USD"
}
},
{
"message": "insufficient funds",
"data": {
"account_id": "acc987654321",
"current_balance": 50.00,
"required_balance": 150.00
}
},
{
"message": "daily withdrawal limit exceeded",
"data": {
"account_id": "acc987654321",
"daily_limit": 1000.00,
"amount_attempted": 1500.00
}
}
]
}
In this example, the error message is composed of three parts:
Each part of the error message has its own section of data, providing detailed context for each part of the error. This structure allows clients to understand the specific context and data related to each part of the error message, making it easier to debug and resolve issues.
Problem Details
The Problem Details RFC is a standardized format for representing errors in HTTP APIs. It defines a structured way to provide detailed information about errors in a machine-readable format, making it easier for clients to understand and handle errors effectively.
Example
{
"status": 400,
"title": "Insufficient Funds",
"detail": "The account '987654321' has insufficient funds for the transaction.",
"type": "https://example.com/probs/insufficient-funds",
"instance": "/accounts/12345/transactions/67890",
"extra_custom_key": "current_balance",
"extra_custom_value": 50.00,
"extra_custom_key2": "required_balance",
"extra_custom_value2": 100.00
}
Differences Between HTTP Wire Errors and Problem Details
While both HTTP Wire Errors and Problem Details provide a structured way to represent errors in HTTP APIs, there are some key differences:
What Problem Details Were Missing
Problem Details (RFC 7807) provide a standardized format for representing errors, but they lack some features that are addressed by HTTP Wire Errors:
How HTTP Wire Errors Provide a Solution
HTTP Wire Errors address these limitations by:
Author
Gerasimos Maropoulos is the author of the Iris web framework, a highly efficient and feature-rich web framework for the Go programming language. He is well-known in the programming community for his contributions to web development and his expertise in the Go language. Gerasimos has authored numerous online articles and tutorials that help developers understand and leverage the power of Go for building scalable and high-performance web applications. His work on Iris has made it one of the most popular web frameworks in the Go ecosystem, known for its simplicity, speed, and extensive feature set.
Gerasimos wrote this RFC to address the need for a standardized approach to handling and representing HTTP wire errors. By providing a clear and consistent structure for error responses, he aims to make it easier for developers to debug and understand the context of errors in their applications. This RFC is part of his ongoing efforts to improve the developer experience and ensure that applications built with Iris are robust and maintainable.
Conclusion
This RFC defines a standardized approach for handling and representing HTTP wire errors. By following this structure, developers can ensure consistent and clear error responses, making it easier for clients to understand and handle errors effectively.