hasura/graphql-engine · error · Error

Error while preparing the response: {0}

Error message

Error while preparing the response: {0}

What it means

The pre-response plugin failed while preparing the final HTTP response object (axum::http::Error) — typically an invalid header name/value or body construction failure when turning the mutated response into an axum response.

Source

Thrown at v3/crates/plugins/pre-response-plugin/src/execute/common.rs:31

use tracing_util::{ErrorVisibility, TraceableError};

#[derive(Debug, thiserror::Error)]
pub enum Error {
    #[error("Error while making the HTTP request to the pre-parse plugin {0} - {1}")]
    ErrorWhileMakingHTTPRequestToTheHook(String, reqwest::Error),
    #[error("Error while building the request for the pre-parse plugin {0} - {1}")]
    BuildRequestError(String, String),
    #[error("Reqwest error: {0}")]
    ReqwestError(reqwest::Error),
    #[error("Error parsing the request: {0}")]
    PluginRequestParseError(serde_json::Error),
    #[error("Error parsing the engine response: {0}")]
    EngineResponseParseError(serde_json::Error),
    #[error("Unexpected status code: {0}")]
    UnexpectedStatusCode(u16),
    #[error("Error serializing the modified response: {0}")]
    ResponseSerializationError(serde_json::Error),
    #[error("Error while preparing the response: {0}")]
    ResponsePreparationError(axum::http::Error),
}

impl TraceableError for Error {
    fn visibility(&self) -> ErrorVisibility {
        ErrorVisibility::Internal
    }
}

impl Error {
    pub fn to_graphql_response(self) -> lang_graphql::http::Response {
        let is_internal = match &self {
            Error::ErrorWhileMakingHTTPRequestToTheHook(_, _)
            | Error::UnexpectedStatusCode(_)
            | Error::ResponseSerializationError(_)
            | Error::ResponsePreparationError(_) => false,
            Error::BuildRequestError(_, _)
            | Error::ReqwestError(_)

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Validate/strip illegal characters from hook-provided header names and values before building the response.
  2. Clamp the hook-supplied status to a valid 100-599 range.
  3. Reject or sanitize CR/LF and control characters in all header data.

Example fix

// before
let name = hook_header.name; // may contain spaces/CRLF
let val = HeaderValue::from_str(&hook_header.value)?;

// after
let name = hook_header.name.trim().replace([' ', '\r', '\n'], "-");
let val = HeaderValue::from_str(&hook_header.value)?;
Defensive patterns

Strategy: validation

Validate before calling

fn valid_header(name: &str, value: &str) -> bool {
    http::HeaderName::from_str(name).is_ok() && http::HeaderValue::from_str(value).is_ok()
}

Try / catch

match build_response(modified) {
    Ok(r) => r,
    Err(Error::ResponsePreparationError(_)) => original_response(), // fall back to unmodified response
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: The hook-supplied headers or status produce an invalid http::Response — e.g. a header name with spaces, an invalid status code number, or a non-UTF8 header value.

Common situations: Hook injecting custom headers from user input without validation; status code outside 100-599; CR/LF injection in header values.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/42f9b55e428b8059. Report an issue: GitHub.