quickwit-oss/quickwit · error

unknown function `{}`

Error message

unknown function `{}`

What it means

The routing expression grammar only recognizes the `hash_mod` function; any other function name in the AST falls through to this catch-all bail in `convert_ast`. It interpolates the unrecognized function name.

Source

Thrown at quickwit/quickwit-doc-mapper/src/routing_expression/mod.rs:311

                            "invalid arguments for `hash_mod`: expected 2 arguments, found {}",
                            args.len()
                        );
                    }

                    let Argument::Expression(fields) = args.remove(0) else {
                        anyhow::bail!("invalid 1st argument for `hash_mod`: expected expression");
                    };

                    let Argument::Number(modulo) = args.remove(0) else {
                        anyhow::bail!("invalid 2nd argument for `hash_mod`: expected number");
                    };

                    Ok(InnerRoutingExpr::Modulo(
                        Box::new(convert_ast(fields)?),
                        modulo,
                    ))
                }
                _ => anyhow::bail!("unknown function `{}`", name),
            },
        })
        .collect::<Result<Vec<_>, _>>()?;
    if result.is_empty() {
        Ok(InnerRoutingExpr::default())
    } else if result.len() == 1 {
        Ok(result.remove(0))
    } else {
        Ok(InnerRoutingExpr::Composite(result))
    }
}

// The display implementation should be consistent with `FromString`.
impl Display for InnerRoutingExpr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self {
            InnerRoutingExpr::Field(field) => {
                for (index, part) in field.iter().enumerate() {

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Use the supported function name `hash_mod`: `hash_mod(field, modulo)`.
  2. Correct typos in the function name in the routing_expression config value.
  3. If you need a different partitioning scheme, implement it as an expression without functions or extend the parser upstream.

Example fix

// before
routing_expression: mod(tenant_id, 4)
// after
routing_expression: hash_mod(tenant_id, 4)
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED_ROUTING_FUNCS: &[&str] = &["hash_mod"];
fn validate_routing_fn(name: &str) -> Result<(), String> {
    if ALLOWED_ROUTING_FUNCS.contains(&name) { Ok(()) }
    else { Err(format!("unknown routing function: {}", name)) }
}

Prevention

When it happens

Trigger: Calling `RoutingExpr::from_str` with a function-style expression whose name is not `hash_mod`, e.g. `mod(tenant_id, 4)` or `hash(tenant_id)`.

Common situations: Assuming other hash/partition functions exist (e.g. mimicking Elasticsearch `mod`); typos like `hashmode` or `hash_md`; copying routing expressions from other systems.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/d1b1e57d6f773436. Report an issue: GitHub.