{"record":{"id":"ed5cd7a0555d61ce","repo":"hasura/graphql-engine","slug":"unexpected-status-code-0-ed5cd7","errorCode":null,"errorMessage":"Unexpected status code: {0}","messagePattern":"Unexpected status code: (.+?)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/crates/plugins/pre-ndc-response-plugin/src/execute.rs","lineNumber":22,"sourceCode":"use metadata_resolve::{DataConnectorLink, Qualified, ResolvedLifecyclePreNdcResponsePluginHook};\nuse open_dds::data_connector::DataConnectorName;\nuse reqwest::{\n    Client,\n    header::{InvalidHeaderName, InvalidHeaderValue},\n};\nuse serde::{Deserialize, Serialize};\nuse std::{collections::BTreeMap, str::FromStr, sync::Arc};\nuse tracing_util::{ErrorVisibility, SpanVisibility, TraceableError, set_attribute_on_active_span};\n\n#[derive(Debug, thiserror::Error)]\npub enum Error {\n    #[error(\"Error while making the HTTP request to the pre-response plugin {0} - {1}\")]\n    ErrorWhileMakingHTTPRequestToTheHook(String, reqwest::Error),\n    #[error(\"Error while building the request for the pre-response plugin {0} - {1}\")]\n    BuildRequestError(String, #[source] BuildRequestError),\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(\"Internal error from plugin {plugin_name}\")]\n    PluginInternalError {\n        plugin_name: String,\n        error: serde_json::Value,\n    },\n    #[error(\"User error from plugin {plugin_name}\")]\n    PluginUserError {\n        plugin_name: String,\n        error: serde_json::Value,\n    },\n}\n\n#[derive(Debug, thiserror::Error)]\npub enum BuildRequestError {\n    #[error(\"Invalid header name {header_name}: {error}\")]","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/v3/crates/plugins/pre-ndc-response-plugin/src/execute.rs#L4-L40","documentation":"The pre-NDC-response plugin replied with an HTTP status code the engine does not recognize as part of the hook protocol (anything other than the expected success and defined error statuses). The numeric status is included. This means the plugin endpoint is reachable but behaving as a plain HTTP service rather than a hook — e.g. 404 from a wrong path, or 502/503 from an ingress in front of it.","triggerScenarios":"The webhook URL points at the wrong path so the server returns 404, or an ingress/gateway in front of the plugin returns 502/503/504, and the engine maps the unknown code to UnexpectedStatusCode(code).","commonSituations":"Wrong path or port in plugin webhook config (404s); plugin behind a load balancer that returns 503 during deploys; auth middleware in front of the plugin returning 401/403.","solutions":["Check which status code appears and curl the exact webhook URL to see the raw response","Correct the path/port in the plugin webhook config","Bypass or configure auth middleware on the plugin route so hook requests reach the plugin","Ensure the plugin returns the protocol's expected status codes on success"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let status = resp.status();\nassert!(status.is_success() || EXPECTED_ERROR_STATUSES.contains(&status.as_u16()), \"unexpected {}\", status);","typeGuard":null,"tryCatchPattern":"let code = resp.status().as_u16();\nif !EXPECTED.contains(&code) {\n    let body = resp.text().await.unwrap_or_default();\n    tracing::error!(code, body, \"unexpected hook status\");\n}","preventionTips":["Point the webhook at the exact hook path","Don't put auth-protected or rewriting proxies in front of the plugin"],"tags":["rust","http","status-code","plugin","webhook"],"backgroundTag":"unexpected-http-status-code","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}