hasura/graphql-engine · error · ConditionError

Number for {side}-hand value of comparison operation is outs

Error message

Number for {side}-hand value of comparison operation is outside precision or range of a double-precision float

What it means

Thrown by the authorization-rules condition evaluator when one side of a comparison operation (e.g. _eq, _gt, _lte on numbers) holds a number that cannot be represented exactly as an f64 double-precision float. The engine compares numeric values as doubles, so values requiring more precision (e.g. huge integers or high-precision decimals) are rejected rather than silently rounded.

Source

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

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,
    session_variables: &SessionVariables,
) -> Result<bool, ConditionError> {
    match condition {
        Condition::All(conditions) => conditions.iter().try_fold(true, |acc, condition| {
            Ok(acc && evaluate_condition(condition, session_variables)?)
        }),

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Reduce the compared value's magnitude/precision so it fits exactly in a double (integers within ±2^53)
  2. Store and compare the value as a string instead of a number if exactness matters
  3. Move the comparison out of the permission rule into application logic or a computed expression that supports arbitrary precision

Example fix

// before
{ "type": "_eq", "left": { "column": "snowflake_id" }, "right": 9007199254740993 }
// after
{ "type": "_eq", "left": { "column": "snowflake_id_str" }, "right": "9007199254740993" }
Defensive patterns

Strategy: validation

Validate before calling

fn fits_f64(n: &serde_json::Number) -> bool {
    if let Some(i) = n.as_i64() {
        i.abs() <= (2i64.pow(53))
    } else {
        n.as_f64().map(|f| serde_json::Number::from_f64(f).as_ref() == Some(n)).unwrap_or(false)
    }
}
assert!(fits_f64(&right_hand_value));

Type guard

fn isDoubleSafe(n: serde_json::Number) -> bool {
    n.as_f64()
        .and_then(|f| serde_json::Number::from_f64(f))
        .map(|rt| rt == n)
        .unwrap_or(false)
}

Try / catch

match condition_eval {
    Err(ConditionError::NumberOutOfRange { side }) => return_policy_deny_with_reason(side),
    r => r,
}

Prevention

When it happens

Trigger: Defining a permission rule with a comparison operator where the left-hand (session variable/column) or right-hand (literal) value is an integer exceeding 2^53 or a decimal with more precision than an f64 can hold, and the value then fails to round-trip through f64.

Common situations: Using 64-bit or UUID-like numeric IDs, snowflake IDs, or high-precision decimal literals in permission comparison expressions in OpenDD auth configuration.

Related errors


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