hasura/graphql-engine · error · ConditionError

Condition {condition_hash} not found

Error message

Condition {condition_hash} not found

What it means

The engine keeps named, reusable comparison expressions (ConditionHash-addressed) for authorization rules. When a role's permission references a condition by hash/ID that is not registered in the loaded set, ConditionError::ConditionNotFound is thrown — the rule points at a condition the engine never loaded or has since discarded.

Source

Thrown at v3/crates/auth/authorization-rules/src/condition.rs:19

//! this is where we evaluate Conditions

use std::fmt::Display;

use hasura_authn_core::{SessionVariableName, SessionVariables};

use crate::ConditionCache;
use metadata_resolve::{
    BinaryOperation, Condition, ConditionHash, Conditions, UnaryOperation, ValueExpression,
};
use open_dds::query::ArgumentName;

#[derive(Debug, PartialEq, Eq, thiserror::Error)]
pub enum ConditionError {
    #[error("Session variable not found: {name}")]
    SessionVariableNotFound { name: SessionVariableName },
    #[error("Serde error: {error}")]
    SerdeError { error: String },
    #[error("Condition {condition_hash} not found")]
    ConditionNotFound { condition_hash: ConditionHash },
    #[error("Expected array or null for right-hand value of contains operation")]
    ExpectedArrayOrNullForContains,
    #[error("Expected number for {side}-hand value of comparison operation")]
    ExpectedNumberForComparison { side: Side },
    #[error(
        "Number for {side}-hand value of comparison operation is outside precision or range of a double-precision float"
    )]
    NumberOutOfRange { side: Side },
    #[error(
        "Tried to combine a predicate with a literal in argument presets for argument {argument_name}"
    )]
    CouldNotCombinePredicateAndLiteralArgumentPresets { argument_name: ArgumentName },
}

// evaluate conditions used in permissions
fn evaluate_condition(
    condition: &Condition,

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Run metadata consistency checks / re-apply the full metadata set atomically so expressions and roles are in sync
  2. Fix the dangling reference: either restore the comparison expression or remove it from the role's rule
  3. Upgrade CLI and engine together so condition hashing stays consistent
  4. If it happens transiently during deploys, retry after metadata apply completes

Example fix

# before: role references a deleted expression
permissions:
  - role: user
    filter: { expression: deleted_expr }
# after
permissions:
  - role: user
    filter: { expression: existing_expr }
Defensive patterns

Strategy: validation

Validate before calling

// Before applying, check every role filter references an existing comparison expression
const names = new Set(expressions.map(e => e.name));
for (const p of permissions) if (p.filter?.expression && !names.has(p.filter.expression)) throw new Error(`Dangling expression: ${p.filter.expression}`);

Type guard

const expressionExists = (defs: {name:string}[], ref: string): boolean => defs.some(d => d.name === ref);

Try / catch

match check { Err(ConditionError::ConditionNotFound { .. }) => retry_after_metadata_apply(), ... }

Prevention

When it happens

Trigger: Metadata where a role permission references a comparison expression whose hash does not exist (renamed/deleted expression), or partially-applied/atomic-metadata inconsistency where expressions and the roles using them drift apart.

Common situations: Deleting or renaming a comparison expression while a role still references it; applying metadata non-atomically; engine/metadata version skew changing how condition hashes are computed; concurrent metadata apply during request handling.

Related errors


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