DEV Community

Cover image for RFC: HTTP Wire Errors

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:

  • id: A unique identifier for the error instance.
  • http_error_code: An object containing:
    • canonical_name: A string representing the canonical name of the error.
    • status: An integer representing the HTTP status code.
  • message: A short, human-readable summary of the error.
  • detail: A human-readable explanation specific to this occurrence of the error.
  • data (optional): Additional data related to the error.
  • validation (optional): An array of validation errors, each containing:
    • field: The name of the field that caused the validation error.
    • value: The invalid value provided.
    • reason: A human-readable explanation of why the value is invalid.

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"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Canonical Error Names

The following canonical error names are defined:

  • INVALID_ARGUMENT: Indicates that the client provided an invalid argument.
  • FAILED_PRECONDITION: Indicates that the operation was rejected because the system is not in a state required for the operation's execution.
  • OUT_OF_RANGE: Indicates that an operation was attempted past the valid range.
  • UNSUPPORTED_MEDIA_TYPE: Indicates that the request entity has a media type which the server or resource does not support.
  • DEADLINE_EXCEEDED: Indicates that the deadline expired before the operation could complete.
  • NOT_FOUND: Indicates that the requested resource could not be found.
  • METHOD_NOT_ALLOWED: Indicates that the HTTP method used is not supported by the resource.
  • ALREADY_EXISTS: Indicates that the resource that a client tried to create already exists.
  • ABORTED: Indicates that the operation was aborted, typically due to a concurrency issue.
  • PERMISSION_DENIED: Indicates that the caller does not have permission to execute the specified operation.
  • UNAUTHENTICATED: Indicates that the request does not have valid authentication credentials for the operation.
  • RESOURCE_EXHAUSTED: Indicates that some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space.
  • TOO_LARGE: Indicates that the request entity is larger than limits defined by server.
  • UNIMPLEMENTED: Indicates that the operation is not implemented or not supported/enabled in this service.
  • UNAVAILABLE: Indicates that the service is currently unavailable.
  • INTERNAL: Indicates an internal server error.
  • DATA_LOSS: Indicates unrecoverable data loss or corruption.
  • UNKNOWN: Indicates an unknown error.
  • PAYMENT_REQUIRED: Indicates that payment is required to access the resource.
  • NOT_ACCEPTABLE: Indicates that the resource is not capable of generating content acceptable according to the Accept headers sent in the request.
  • PROXY_AUTH_REQUIRED: Indicates that the client must first authenticate itself with the proxy.
  • REQUEST_TIMEOUT: Indicates that the server timed out waiting for the request.
  • GONE: Indicates that the resource requested is no longer available and will not be available again.
  • LENGTH_REQUIRED: Indicates that the request did not specify the length of its content, which is required by the requested resource.
  • PRECONDITION_FAILED: Indicates that the server does not meet one of the preconditions that the requester put on the request.
  • REQUEST_URI_TOO_LONG: Indicates that the URI provided was too long for the server to process.
  • REQUESTED_RANGE_NOT_SATISFIABLE: Indicates that the server cannot supply the portion of the file requested.
  • EXPECTATION_FAILED: Indicates that the server cannot meet the requirements of the Expect request-header field.
  • IM_A_TEAPOT: Indicates that the server refuses to brew coffee because it is, permanently, a teapot.
  • MISDIRECTED_REQUEST: Indicates that the request was directed at a server that is not able to produce a response.
  • UNPROCESSABLE_ENTITY: Indicates that the server understands the content type of the request entity, but was unable to process the contained instructions.
  • LOCKED: Indicates that the resource that is being accessed is locked.
  • FAILED_DEPENDENCY: Indicates that the request failed due to failure of a previous request.
  • TOO_EARLY: Indicates that the server is unwilling to risk processing a request that might be replayed.
  • UPGRADE_REQUIRED: Indicates that the client should switch to a different protocol.
  • PRECONDITION_REQUIRED: Indicates that the origin server requires the request to be conditional.
  • REQUEST_HEADER_FIELDS_TOO_LARGE: Indicates that the server is unwilling to process the request because its header fields are too large.
  • UNAVAILABLE_FOR_LEGAL_REASONS: Indicates that the resource is unavailable for legal reasons.
  • HTTP_VERSION_NOT_SUPPORTED: Indicates that the server does not support the HTTP protocol version used in the request.
  • VARIANT_ALSO_NEGOTIATES: Indicates that the server has an internal configuration error.
  • INSUFFICIENT_STORAGE: Indicates that the server is unable to store the representation needed to complete the request.
  • LOOP_DETECTED: Indicates that the server detected an infinite loop while processing a request.
  • NOT_EXTENDED: Indicates that further extensions to the request are required for the server to fulfill it.
  • NETWORK_AUTHENTICATION_REQUIRED: Indicates that the client needs to authenticate to gain network access.
  • PAGE_EXPIRED: Indicates that the page has expired.
  • BLOCKED_BY_WINDOWS_PARENTAL_CONTROLS: Indicates that the request was blocked by Windows Parental Controls.
  • INVALID_TOKEN: Indicates that the token provided is invalid.
  • TOKEN_REQUIRED: Indicates that a token is required to access the resource.
  • BANDWIDTH_LIMIT_EXCEEDED: Indicates that the bandwidth limit has been exceeded.
  • INVALID_SSL_CERTIFICATE: Indicates that the SSL certificate is invalid.
  • SITE_OVERLOADED: Indicates that the site is overloaded.
  • SITE_FROZEN: Indicates that the site is frozen.
  • NETWORK_READ_TIMEOUT: Indicates that there was a network read timeout error.

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"
}
Enter fullscreen mode Exit fullscreen mode

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
    }
}
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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"
    }
}
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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
            }
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

In this example, the error message is composed of three parts:

  1. transaction failed
  2. insufficient funds
  3. daily withdrawal limit exceeded

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
}
Enter fullscreen mode Exit fullscreen mode

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:

  1. Flexibility: HTTP Wire Errors offer a more flexible structure that can include additional fields such as id, http_error_code, message, data, and validation. This allows for more detailed and context-specific error information.

  2. Canonical Error Names: HTTP Wire Errors define a set of canonical error names that standardize common error scenarios, making it easier to categorize and handle errors consistently across different parts of an application.

  3. Nested Data: HTTP Wire Errors support nested data structures, allowing for detailed context for each part of a complex error message. This is particularly useful for errors that involve multiple related issues.

  4. Validation Errors: HTTP Wire Errors include a dedicated validation field to provide detailed information about validation errors, including the specific fields and reasons for the validation failure.

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:

  • Canonical Error Names: Problem Details do not define a set of canonical error names, which can lead to inconsistencies in error categorization.
  • Nested Data: Problem Details do not natively support nested data structures, making it harder to provide detailed context for complex errors.
  • Validation Errors: Problem Details do not have a dedicated field for validation errors, which can make it harder to provide detailed information about validation issues.

How HTTP Wire Errors Provide a Solution

HTTP Wire Errors address these limitations by:

  • Defining a set of canonical error names for consistent error categorization.
  • Supporting nested data structures to provide detailed context for complex errors.
  • Including a dedicated validation field for detailed validation error information.

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.

Top comments (0)