hasura/graphql-engine · error · Error

Error parsing the request: {0}

Error message

Error parsing the request: {0}

What it means

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.

Source

Thrown at v3/crates/plugins/pre-ndc-request-plugin/src/execute.rs:24

use reqwest::{
    Client,
    header::{InvalidHeaderName, InvalidHeaderValue},
};
use serde::{Deserialize, Serialize};
use std::{collections::BTreeMap, str::FromStr, sync::Arc};
use tracing_util::{ErrorVisibility, SpanVisibility, 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, #[source] BuildRequestError),
    #[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("Internal error from plugin {plugin_name}")]
    PluginInternalError {
        plugin_name: String,
        error: serde_json::Value,
    },
    #[error("User error from plugin {plugin_name}")]
    PluginUserError {
        plugin_name: String,
        error: serde_json::Value,
    },
}

#[derive(Debug, thiserror::Error)]
pub enum BuildRequestError {
    #[error("Invalid header name {header_name}: {error}")]
    InvalidHeaderName {
        header_name: String,

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Verify the plugin's response body actually contains the full mutated NDC request JSON and not a wrapper object or error payload
  2. Check that the plugin crate version matches the engine version (rebuild/redeploy both together)
  3. Log the raw response body before parsing to see exactly what the plugin returned
  4. If you wrote the plugin yourself, make sure you serialize the same request struct you deserialized, with no extra/renamed fields

Example fix

// before (plugin returns a wrapper)
{ "request": ndc_request, "metadata": ... }
// after (plugin returns the request directly)
serde_json::to_value(&ndc_request)
Defensive patterns

Strategy: validation

Validate before calling

// before parsing, assert the body looks like the expected request shape
let body: serde_json::Value = resp.json().await?;
if body.get("query").is_none() { /* log body, likely wrapper/error object */ }

Try / catch

match resp.json::<PluginRequest>() {
    Ok(r) => r,
    Err(e) => {
        tracing::error!(body = ?raw_body, "plugin response parse failed");
        return Err(Error::PluginRequestParseError(e));
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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