{"record":{"id":"9af8943c7e48c269","repo":"quickwit-oss/quickwit","slug":"invalid-1st-argument-for-hash-mod-expected-expr","errorCode":null,"errorMessage":"invalid 1st argument for `hash_mod`: expected expression","messagePattern":"invalid 1st argument for `hash_mod`: expected expression","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-doc-mapper/src/routing_expression/mod.rs","lineNumber":299,"sourceCode":"        .map(|ast_elem| match ast_elem {\n            ExpressionAst::Field(field_name) => {\n                let field_path = expression_dsl::parse_field_name(&field_name)?\n                    .into_iter()\n                    .map(Cow::into_owned)\n                    .collect();\n                Ok(InnerRoutingExpr::Field(field_path))\n            }\n            ExpressionAst::Function { name, mut args } => match &*name {\n                \"hash_mod\" => {\n                    if args.len() != 2 {\n                        anyhow::bail!(\n                            \"invalid arguments for `hash_mod`: expected 2 arguments, found {}\",\n                            args.len()\n                        );\n                    }\n\n                    let Argument::Expression(fields) = args.remove(0) else {\n                        anyhow::bail!(\"invalid 1st argument for `hash_mod`: expected expression\");\n                    };\n\n                    let Argument::Number(modulo) = args.remove(0) else {\n                        anyhow::bail!(\"invalid 2nd argument for `hash_mod`: expected number\");\n                    };\n\n                    Ok(InnerRoutingExpr::Modulo(\n                        Box::new(convert_ast(fields)?),\n                        modulo,\n                    ))\n                }\n                _ => anyhow::bail!(\"unknown function `{}`\", name),\n            },\n        })\n        .collect::<Result<Vec<_>, _>>()?;\n    if result.is_empty() {\n        Ok(InnerRoutingExpr::default())\n    } else if result.len() == 1 {","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-doc-mapper/src/routing_expression/mod.rs#L281-L317","documentation":"After checking `hash_mod` arity, `convert_ast` removes the first argument and requires it to be an `Argument::Expression`. If the first argument is not an expression (e.g. a plain number or identifier value), this error is thrown.","triggerScenarios":"Calling `RoutingExpr::from_str` with `hash_mod(10, 4)` or otherwise passing a non-expression (number/other literal) as the first argument of `hash_mod`.","commonSituations":"Swapping the two arguments (`hash_mod(4, tenant_id)`); quoting/escaping issues that turn a field path into a literal; misunderstanding that the first argument must be a field-path expression.","solutions":["Pass a field-path expression as the first argument: `hash_mod(tenant_id, 4)`.","Ensure the field name is not quoted or reduced to a number literal in the routing expression.","Verify the order of arguments — expression first, modulo number second."],"exampleFix":"// before\nrouting_expression: hash_mod(4, tenant_id)\n// after\nrouting_expression: hash_mod(tenant_id, 4)","handlingStrategy":"validation","validationCode":"fn validate_hash_mod_args(args: &[Argument]) -> Result<(), String> {\n    match args.first() {\n        Some(Argument::Expression(_)) => Ok(()),\n        _ => Err(\"first hash_mod argument must be an expression\".into()),\n    }\n}","typeGuard":"fn is_expression(a: &Argument) -> bool { matches!(a, Argument::Expression(_)) }","tryCatchPattern":"match RoutingExpr::from_str(cfg.routing_expression.as_str()) {\n    Ok(expr) => expr,\n    Err(e) if e.to_string().contains(\"hash_mod\") => return Err(ConfigError::Routing(e)),\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Pass the field path as the first hash_mod argument, never a literal.","Lint routing expression configs for argument order before deployment.","Document the signature hash_mod(<field-expr>, <number>) for config authors."],"tags":["routing","config","argument-type"],"backgroundTag":"invalid-argument-value","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}