{"record":{"id":"67646416db08b44f","repo":"quickwit-oss/quickwit","slug":"invalid-2nd-argument-for-hash-mod-expected-numb","errorCode":null,"errorMessage":"invalid 2nd argument for `hash_mod`: expected number","messagePattern":"invalid 2nd argument for `hash_mod`: expected number","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-doc-mapper/src/routing_expression/mod.rs","lineNumber":303,"sourceCode":"                    .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 {\n        Ok(result.remove(0))\n    } else {\n        Ok(InnerRoutingExpr::Composite(result))\n    }","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-doc-mapper/src/routing_expression/mod.rs#L285-L321","documentation":"While converting the routing expression AST in `convert_ast`, the `hash_mod(...)` function was given a second argument that is not a number literal. `hash_mod` requires exactly two arguments: a field path and a numeric modulus, so the parser rejects the malformed expression.","triggerScenarios":"Calling `RoutingExpr::from_str` with `hash_mod(tenant_id, tenant_id)` or `hash_mod(tenant_id, \"4\")` — the second argument is not a numeric literal.","commonSituations":"Quoting the modulo value; accidentally passing a second field name; generating routing expressions programmatically and inserting the modulo as a string.","solutions":["Use a bare integer as the second argument: `hash_mod(tenant_id, 4)`.","Remove surrounding quotes from the modulo value in the config.","Double-check the argument order: expression first, plain number second."],"exampleFix":"// before\nrouting_expression: hash_mod(tenant_id, \"4\")\n// after\nrouting_expression: hash_mod(tenant_id, 4)","handlingStrategy":"validation","validationCode":"fn validate_hash_mod_modulo(args: &[Argument]) -> Result<(), String> {\n    match args.get(1) {\n        Some(Argument::Number(n)) if *n > 0 => Ok(()),\n        _ => Err(\"second hash_mod argument must be a number\".into()),\n    }\n}","typeGuard":"fn is_number(a: &Argument) -> bool { matches!(a, Argument::Number(_)) }","tryCatchPattern":null,"preventionTips":["Write the modulo as a bare unquoted integer.","Reject quoted modulo values when generating routing expressions programmatically.","Test routing expression strings with from_str in unit tests before shipping configs."],"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"}