hasura/graphql-engine · error · Error

Unexpected status code: {0}

Error message

Unexpected status code: {0}

What it means

The pre-response hook returned an HTTP status code the executor does not treat as success (or as its continue signal). The numeric code is included in the message.

Source

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

use lang_graphql::{ast::common as ast, http::RawRequest};
use open_dds::plugins::{LifecyclePluginUrl, LifecyclePreResponsePluginHookConfigRequest};
use reqwest::header::HeaderValue;
use serde::Serialize;
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(_)

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Check the hook service logs for the failing request.
  2. Confirm the endpoint path and method the engine calls match what the plugin exposes.
  3. Align auth configuration between engine and hook.
  4. Upgrade both sides together so the status contract matches.
Defensive patterns

Strategy: try-catch

Try / catch

if let Error::UnexpectedStatusCode(code) = e {
    // 401/403: fix auth; 404: fix path; 5xx: check hook logs; consider fail-open
}

Prevention

When it happens

Trigger: The pre-response hook replies 4xx/5xx — e.g. it rejects the modified-response payload, hits an internal error (500), or requires auth the engine doesn't provide.

Common situations: Hook endpoint path changed between versions returning 404; auth token mismatch returning 401; plugin bug returning 500 on edge-case responses.

Related errors


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