hasura/graphql-engine · error · Error

HTTP method {0} not supported

Error message

HTTP method {0} not supported

What it means

The pre-route hook returned a routing instruction whose HTTP method string is not supported by the executor — the {0} field contains the rejected method name. Only a known set of methods can be applied to the rewritten/routed request.

Source

Thrown at v3/crates/plugins/pre-route-plugin/src/execute.rs:32

};
use serde_json::json;
use tracing_util::{
    ErrorVisibility, SpanVisibility, Traceable, TraceableError, set_attribute_on_active_span,
};

#[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("Unexpected status code: {0}")]
    UnexpectedStatusCode(u16),
    #[error("Error parsing the request: {0}")]
    PluginRequestParseError(serde_json::error::Error),
    #[error("HTTP method {0} not supported")]
    UnsupportedHTTPMethod(String),
    #[error("Invalid header name {0}")]
    InvalidHeaderName(String),
    #[error("Invalid header value {0}")]
    InvalidHeaderValue(String),
    #[error("Not found")]
    NotFound,
    // Only used in the pre-route plugin handler function. Defined to ensure consistent
    // response formatting in IntoResponse impl.
    #[error("Cannot load pre-route plugins: {0}")]
    CannotLoadPlugins(String),
}

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

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Fix the hook to only return methods the engine supports (GET, POST, PUT, DELETE, HEAD, OPTIONS as documented).
  2. Normalize the method string (trim, uppercase) before returning it from the hook.
  3. Upgrade the engine crate if a newer version added support for the method you need.

Example fix

// before (hook)
{"method": method_from_client} // may be "patch" or custom

// after (hook)
let m = method_from_client.trim().to_uppercase();
assert!(matches!(m.as_str(), "GET"|"POST"|"PUT"|"DELETE"|"HEAD"|"OPTIONS"));
{"method": m}
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED: &[&str] = &["GET","POST","PUT","DELETE","HEAD","OPTIONS"];
fn supported_method(m: &str) -> bool { SUPPORTED.contains(&m.trim().to_uppercase().as_str()) }

Type guard

fn is_supported_method(m: &str) -> bool {
    matches!(m.trim().to_uppercase().as_str(), "GET"|"POST"|"PUT"|"DELETE"|"HEAD"|"OPTIONS")
}

Try / catch

if let Error::UnsupportedHTTPMethod(m) = &e { tracing::warn!("hook sent unsupported method {m}; keeping original"); }

Prevention

When it happens

Trigger: The hook responds with an instruction to rewrite the request using a method like "PATCH", "TRACE", or a custom string that the executor's match does not handle.

Common situations: Hook written to forward arbitrary client methods; typo'd method name ("GET " with whitespace, lowercase mismatch); newer method support added to the hook but not the engine crate version in use.

Related errors


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