hasura/graphql-engine · error · ExecutePreResponsePluginsError

error in executing pre-response plugins, unable to encode re

Error message

error in executing pre-response plugins, unable to encode response: {0}

What it means

Raised when a pre-response plugin produced a response that could not be serialized to JSON (`serde_json::Error`), reported via `ExecutePreResponsePluginsError::EncodeError`. After pre-response plugins mutate the response, it must be encoded to JSON for the websocket frame; invalid data (e.g. a map with a non-string key) fails encoding.

Source

Thrown at v3/crates/graphql/graphql-ws/src/protocol/subscribe.rs:753

                        send_graphql_errors(operation_id, errors, connection).await;
                        stop_subscription = true;
                    }
                }
            }
            GraphQLResponseOrCustomResponse::CustomResponse(bytes) => {
                connection
                    .send(ws::Message::Raw(axum::extract::ws::Message::Binary(bytes)))
                    .await;
            }
        }
    }
    stop_subscription
}

#[derive(thiserror::Error, Debug)]
#[error("error in executing pre-response plugins, unable to encode response: {0}")]
enum ExecutePreResponsePluginsError {
    #[error("error in executing pre-response plugins, unable to encode response: {0}")]
    EncodeError(#[from] serde_json::Error),
    #[error("error in executing pre-response plugins: {0}")]
    PreResponsePluginError(#[from] pre_response_plugin::Error),
}

impl tracing_util::TraceableError for ExecutePreResponsePluginsError {
    fn visibility(&self) -> tracing_util::ErrorVisibility {
        tracing_util::ErrorVisibility::User
    }
}

async fn run_pre_response_plugins<M: WebSocketMetrics>(
    client_address: std::net::SocketAddr,
    raw_request: &lang_graphql::http::RawRequest,
    session: Session,
    headers: http::HeaderMap,
    response: &lang_graphql::http::Response,
    connection: &ws::Connection<M>,

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Log the serde_json error to find the offending field in the plugin's response
  2. Replace non-serializable constructs (use string keys, handle NaN via arithmetic checks or serde_json 'arbitrary_precision'/'float_roundtrip' features)
  3. Add unit tests serializing the plugin output with serde_json::to_value in CI
  4. Run the plugin chain in a dev environment with representative payloads before deploying

Example fix

// before (Rust plugin)
let meta: HashMap<u32, String> = build_meta();
// after
let meta: BTreeMap<String, String> = build_meta().into_iter().map(|(k,v)|(k.to_string(),v)).collect();
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust: verify plugin output is JSON-encodable before returning
serde_json::to_value(&response)?;

Try / catch

match err { ExecutePreResponsePluginsError::EncodeError(e) => log::error!("encode: {e}"); _ => {} }

Prevention

When it happens

Trigger: A pre-response plugin returns or mutates a response payload containing values serde_json cannot serialize — such as a map with non-string keys, NaN/Infinity floats, or a type without Serialize — during subscription response processing.

Common situations: Custom plugin serializing HashMap<NonStringKey, _>; floats becoming NaN through computation; plugin version change introducing a non-serializable field; custom Serialize impl returning an error.

Related errors


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