{"record":{"id":"50bb257f9cf335a9","repo":"hasura/graphql-engine","slug":"error-parsing-the-request-0","errorCode":null,"errorMessage":"Error parsing the request: {0}","messagePattern":"Error parsing the request: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/crates/plugins/pre-ndc-request-plugin/src/execute.rs","lineNumber":24,"sourceCode":"use 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-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, #[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}\")]\n    InvalidHeaderName {\n        header_name: String,","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/v3/crates/plugins/pre-ndc-request-plugin/src/execute.rs#L6-L42","documentation":"This error is thrown by the pre-NDC-request plugin executor when the HTTP response body returned by the plugin cannot be parsed back into the expected request shape; the {0} placeholder carries the underlying serde_json error. It means the plugin server replied with a 200 response whose JSON does not match the serialized NDC request schema expected by the connector. It almost always indicates a plugin version mismatch or a plugin implementation bug.","triggerScenarios":"Calling a pre-request hook plugin over HTTP, receiving a successful status code, and failing at resp.json::<...>() deserialization of the plugin's mutated request payload.","commonSituations":"Upgrading the engine but not the plugin (or vice versa) so the request schema changed; a plugin returning a wrapped or empty body instead of the raw mutated NDC request; a plugin returning an error object with HTTP 200.","solutions":["Verify the plugin's response body actually contains the full mutated NDC request JSON and not a wrapper object or error payload","Check that the plugin crate version matches the engine version (rebuild/redeploy both together)","Log the raw response body before parsing to see exactly what the plugin returned","If you wrote the plugin yourself, make sure you serialize the same request struct you deserialized, with no extra/renamed fields"],"exampleFix":"// before (plugin returns a wrapper)\n{ \"request\": ndc_request, \"metadata\": ... }\n// after (plugin returns the request directly)\nserde_json::to_value(&ndc_request)","handlingStrategy":"validation","validationCode":"// before parsing, assert the body looks like the expected request shape\nlet body: serde_json::Value = resp.json().await?;\nif body.get(\"query\").is_none() { /* log body, likely wrapper/error object */ }","typeGuard":null,"tryCatchPattern":"match resp.json::<PluginRequest>() {\n    Ok(r) => r,\n    Err(e) => {\n        tracing::error!(body = ?raw_body, \"plugin response parse failed\");\n        return Err(Error::PluginRequestParseError(e));\n    }\n}","preventionTips":["Deploy engine and plugin from the same release artifact set","Add a contract test asserting the plugin round-trips a sample request"],"tags":["rust","plugin","deserialization","http","ndc"],"backgroundTag":"json-deserialization-mismatch","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}