hasura/graphql-engine · error · InternalDeveloperError::MissingSessionVariable

Required session variable not found in the request: {session

Error message

Required session variable not found in the request: {session_variable}

What it means

Internal developer error from the plan crate: a session variable referenced in the query (e.g. in an argument preset or expression) was required but was not present in the incoming request's session variables (e.g. Hasura request headers like x-hasura-user-id).

Source

Thrown at v3/crates/plan/src/error.rs:33

pub enum InternalError {
    #[error("{0}")]
    Developer(#[from] InternalDeveloperError),
    #[error("{0}")]
    Engine(#[from] InternalEngineError),
}

impl TraceableError for InternalError {
    fn visibility(&self) -> ErrorVisibility {
        match self {
            Self::Developer(error) => error.visibility(),
            Self::Engine(_) => ErrorVisibility::Internal,
        }
    }
}

#[derive(Debug, thiserror::Error)]
pub enum InternalDeveloperError {
    #[error("Required session variable not found in the request: {session_variable}")]
    MissingSessionVariable {
        session_variable: SessionVariableName,
    },

    #[error(
        "The session variables {session_variable} is not encoded as a string. JSON-typed session variables are not supported unless you update your compatibility date"
    )]
    VariableJsonNotSupported {
        session_variable: SessionVariableName,
    },

    #[error(
        "Session variable {session_variable} value is of an unexpected type. Expected: {expected}, but found: {found}"
    )]
    VariableTypeCast {
        session_variable: SessionVariableName,
        expected: String,
        found: String,

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Send the missing session variable as a request header (x-hasura-<name>) or via the session_variables field of the request
  2. If the variable is optional, give the expression a fallback/default so it is not required
  3. Check the argument preset / permission rule that references the variable and confirm the exact variable name clients must send

Example fix

# before
curl .../graphql -d '{ user(id: 1) { ... } }'   # preset needs x-hasura-user-id
# after
curl .../graphql -H 'x-hasura-user-id: 1' -d '{ user(id: 1) { ... } }'
Defensive patterns

Strategy: validation

Validate before calling

// Before executing, ensure every required session variable is present
for var in plan.required_session_variables() {
    request.session_variables
        .get(var)
        .ok_or_else(|| format!("missing session variable: {var}"))?;
}

Type guard

fn has_all_session_vars(req: &Request, vars: &[&str]) -> bool {
    vars.iter().all(|v| req.session_variables.contains_key(*v))
}

Try / catch

match plan.execute(req) {
    Err(InternalDeveloperError::MissingSessionVariable { session_variable }) => {
        // ask the client to send x-hasura-<name>
    }
    r => r,
}

Prevention

When it happens

Trigger: Executing a planned query whose expression tree contains a SessionVariable reference and the request's session variable set does not contain that key; happens when building NDC queries with argument presets bound to x-hasura-* variables.

Common situations: Testing a query in an environment where auth headers are absent (curl without x-hasura-user-id); renaming a preset's session variable without updating clients; admin/CI bypass that strips headers.

Related errors


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