{"record":{"id":"aaed5a657e2e24c1","repo":"hasura/graphql-engine","slug":"unexpected-status-code-0-aaed5a","errorCode":null,"errorMessage":"Unexpected status code: {0}","messagePattern":"Unexpected status code: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/crates/plugins/pre-route-plugin/src/execute.rs","lineNumber":28,"sourceCode":"\nuse open_dds::plugins::{\n    LifecyclePreRoutePluginHook, LifecyclePreRoutePluginHookConfigRequestMethod,\n    LifecyclePreRoutePluginHookIncomingHTTPMethod,\n};\nuse serde_json::json;\nuse tracing_util::{\n    ErrorVisibility, SpanVisibility, Traceable, TraceableError, set_attribute_on_active_span,\n};\n\n#[derive(Debug, thiserror::Error)]\npub enum Error {\n    #[error(\"Error while making the HTTP request to the pre-parse plugin {0} - {1}\")]\n    ErrorWhileMakingHTTPRequestToTheHook(String, reqwest::Error),\n    #[error(\"Error while building the request for the pre-parse plugin {0} - {1}\")]\n    BuildRequestError(String, String),\n    #[error(\"Reqwest error: {0}\")]\n    ReqwestError(reqwest::Error),\n    #[error(\"Unexpected status code: {0}\")]\n    UnexpectedStatusCode(u16),\n    #[error(\"Error parsing the request: {0}\")]\n    PluginRequestParseError(serde_json::error::Error),\n    #[error(\"HTTP method {0} not supported\")]\n    UnsupportedHTTPMethod(String),\n    #[error(\"Invalid header name {0}\")]\n    InvalidHeaderName(String),\n    #[error(\"Invalid header value {0}\")]\n    InvalidHeaderValue(String),\n    #[error(\"Not found\")]\n    NotFound,\n    // Only used in the pre-route plugin handler function. Defined to ensure consistent\n    // response formatting in IntoResponse impl.\n    #[error(\"Cannot load pre-route plugins: {0}\")]\n    CannotLoadPlugins(String),\n}\n\nimpl TraceableError for Error {","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/v3/crates/plugins/pre-route-plugin/src/execute.rs#L10-L46","documentation":"The pre-route hook returned an HTTP status the executor does not accept (anything other than the defined success/continue statuses). The numeric code is embedded in the message.","triggerScenarios":"Hook returns 404 (endpoint moved), 401/403 (auth mismatch), or 500 (hook bug) when the engine calls it before routing.","commonSituations":"Plugin and engine version drift changing the hook path; missing/rotated auth token on the hook; hook failing on specific request shapes.","solutions":["Check hook logs to find why it rejected the call.","Verify the hook route and payload contract match the engine's pre-route plugin version.","Fix auth token configuration on both sides.","Redeploy matching engine/plugin versions."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Error::UnexpectedStatusCode(code) = &err {\n    match code { 401 | 403 => fix_auth(), 404 => fix_hook_path(), _ => inspect_hook_logs() }\n}","preventionTips":["Contract-test hook statuses (success + continue signals) in CI.","Keep hook auth tokens in sync via a shared secret store.","Pin engine and plugin versions together in deployments."],"tags":["http","status-code","plugin","rust","pre-route-hook"],"backgroundTag":"unexpected-http-status","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}