{"record":{"id":"0e1c35465e97ddce","repo":"hasura/graphql-engine","slug":"condition-condition-hash-not-found","errorCode":null,"errorMessage":"Condition {condition_hash} not found","messagePattern":"Condition (.+?) not found","errorType":"error_code","errorClass":"ConditionError","httpStatus":null,"severity":"error","filePath":"v3/crates/auth/authorization-rules/src/condition.rs","lineNumber":19,"sourceCode":"//! this is where we evaluate Conditions\n\nuse std::fmt::Display;\n\nuse hasura_authn_core::{SessionVariableName, SessionVariables};\n\nuse crate::ConditionCache;\nuse metadata_resolve::{\n    BinaryOperation, Condition, ConditionHash, Conditions, UnaryOperation, ValueExpression,\n};\nuse open_dds::query::ArgumentName;\n\n#[derive(Debug, PartialEq, Eq, thiserror::Error)]\npub enum ConditionError {\n    #[error(\"Session variable not found: {name}\")]\n    SessionVariableNotFound { name: SessionVariableName },\n    #[error(\"Serde error: {error}\")]\n    SerdeError { error: String },\n    #[error(\"Condition {condition_hash} not found\")]\n    ConditionNotFound { condition_hash: ConditionHash },\n    #[error(\"Expected array or null for right-hand value of contains operation\")]\n    ExpectedArrayOrNullForContains,\n    #[error(\"Expected number for {side}-hand value of comparison operation\")]\n    ExpectedNumberForComparison { side: Side },\n    #[error(\n        \"Number for {side}-hand value of comparison operation is outside precision or range of a double-precision float\"\n    )]\n    NumberOutOfRange { side: Side },\n    #[error(\n        \"Tried to combine a predicate with a literal in argument presets for argument {argument_name}\"\n    )]\n    CouldNotCombinePredicateAndLiteralArgumentPresets { argument_name: ArgumentName },\n}\n\n// evaluate conditions used in permissions\nfn evaluate_condition(\n    condition: &Condition,","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/hasura/graphql-engine/blob/724551b9ae87845594ef0408cff0e50eb6c90dc5/v3/crates/auth/authorization-rules/src/condition.rs#L1-L37","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run metadata consistency checks / re-apply the full metadata set atomically so expressions and roles are in sync","Fix the dangling reference: either restore the comparison expression or remove it from the role's rule","Upgrade CLI and engine together so condition hashing stays consistent","If it happens transiently during deploys, retry after metadata apply completes"],"exampleFix":"# before: role references a deleted expression\npermissions:\n  - role: user\n    filter: { expression: deleted_expr }\n# after\npermissions:\n  - role: user\n    filter: { expression: existing_expr }","handlingStrategy":"validation","validationCode":"// Before applying, check every role filter references an existing comparison expression\nconst names = new Set(expressions.map(e => e.name));\nfor (const p of permissions) if (p.filter?.expression && !names.has(p.filter.expression)) throw new Error(`Dangling expression: ${p.filter.expression}`);","typeGuard":"const expressionExists = (defs: {name:string}[], ref: string): boolean => defs.some(d => d.name === ref);","tryCatchPattern":"match check { Err(ConditionError::ConditionNotFound { .. }) => retry_after_metadata_apply(), ... }","preventionTips":["Apply metadata atomically; never partial applies","Run metadata consistency checks in CI","Reapply full metadata after renaming/deleting expressions"],"tags":["auth","authorization","metadata","condition","hasura","rust"],"backgroundTag":"dangling-metadata-reference","analyzedSha":"724551b9ae87845594ef0408cff0e50eb6c90dc5","analyzedAt":"2026-08-28T07:32:55.105Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}