hasura/graphql-engine · error · Error

Unexpected value: expecting {expected_kind:}, but found: {fo

Error message

Unexpected value: expecting {expected_kind:}, but found: {found:}

What it means

The IR (intermediate representation) layer throws this when it encounters a JSON value whose kind doesn't match what the IR constructor expected at that position — e.g. a string where an object is required, or an array where a scalar is expected. The message names the expected kind and echoes the offending value, making it a structural validation error on incoming request data.

Source

Thrown at v3/crates/graphql/ir/src/error.rs:46

            }
        }
    }
}

#[allow(clippy::duplicated_attributes)] // suppress spurious warnings from Clippy
#[derive(Error, Debug, Transitive)]
#[transitive(from(json::Error, InternalError))]
#[transitive(from(gql::normalized_ast::Error, InternalError))]
#[transitive(from(InternalEngineError, InternalError))]
#[transitive(from(InternalDeveloperError, InternalError))]
pub enum Error {
    #[error("The global ID {encoded_value:} couldn't be decoded due to {decoding_error:}")]
    FailureDecodingGlobalId {
        encoded_value: String,
        decoding_error: String,
    },

    #[error("Unexpected value: expecting {expected_kind:}, but found: {found:}")]
    UnexpectedValue {
        expected_kind: &'static str,
        found: json::Value,
    },

    #[error("'{name:}' is not a valid GraphQL name.")]
    TypeFieldInvalidGraphQlName { name: String },

    #[error("'{alias:} is not a valid alias")]
    InvalidAlias { alias: String },

    #[error("{value} is not a valid limit value")]
    InvalidLimitValue { value: u32 },

    #[error("{value} is not a valid offset value")]
    InvalidOffsetValue { value: u32 },

    #[error("field '{field_name:} not found in entity representation")]

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Inspect the 'found' value in the error and compare with the documented expected type for that argument/field
  2. Fix the client to send correctly typed JSON (e.g. 42 not "42")
  3. Add client-side schema validation (codegen, zod, etc.) so variables are type-checked before sending

Example fix

// before
variables: {{ filter: {{ count: "10" }} }}

// after
variables: {{ filter: {{ count: 10 }} }}
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof variables.filter?.count !== 'number') {
  throw new TypeError('filter.count must be a number');
}

Type guard

function isRecord(v: unknown): v is Record<string, unknown> {{
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}}

Try / catch

try {{
  await execute(query, variables);
}} catch (e: any) {{
  if (e.message.includes('Unexpected value: expecting')) {{
    // log variables, fix types, retry
  }}
}}

Prevention

When it happens

Trigger: Building IR values from request JSON: a where-clause argument, variable default, or entity representation field receives a JSON value of the wrong type (string given where number/object was expected).

Common situations: Clients sending loosely-typed variables (numbers as strings); schema/serialization drift between what the client sends and what the IR builder expects; hand-crafted JSON requests bypassing generated types.

Related errors


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