quickwit-oss/quickwit · error

error parsing routing expression

Error message

error parsing routing expression: {e}

What it means

The routing expression (partitioning key expression) DSL string is parsed with a nom parser. If the whole string cannot be parsed as a valid routing expression (bad syntax, unbalanced characters, unknown constructs), the parser error is wrapped with this message. It occurs when index partitioning configuration is being interpreted.

Solutions

  1. Check the wrapped parser error `{e}` for position/details and correct the DSL string syntax.
  2. Verify parentheses and the `hash_mod(...)` expression shape in `indexing.partitioning`.
  3. Escape special characters in field names per the routing expression DSL rules.
  4. Test the expression against the documented routing expression grammar for your Quickwit version.

Example fix

# before
partitioning:
  hash_mod: tenant_id
# after
partitioning:
  hash_mod: tenant_id
Defensive patterns

Strategy: try-catch

Validate before calling

// Basic syntax sanity check before applying config
if (!/^hash_mod\([a-zA-Z0-9_.\\]+\)$/.test(expr) && expr.trim() !== "") {
    throw new Error("invalid routing expression syntax");
}

Try / catch

match parse_expression(expr) {
    Err(e) if e.to_string().starts_with("error parsing routing expression") => {
        // surface the wrapped nom error position to the user
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling `parse_expression` on a `routing_expression` / partitioning DSL string from the index config that is syntactically invalid, e.g. `hash_mod(field_name`, stray characters, or missing closing parentheses.

Common situations: Hand-written `indexing.partitioning` config with typos, generated config where a field name contains characters the DSL treats specially, or copy-paste from docs of a different version with changed syntax.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

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

    use nom::{AsChar, Finish, IResult, Input, Parser};

    // this is a RoutingSubExpr in our DSL.
    #[derive(Debug, PartialEq, Eq, Clone)]
    pub(crate) enum ExpressionAst {
        Field(String),
        Function { name: String, args: Vec<Argument> },
    }

    #[derive(Debug, PartialEq, Eq, Clone)]
    pub(crate) enum Argument {
        Expression(Vec<ExpressionAst>),
        Number(u64),
    }

    pub(crate) fn parse_expression(expr_dsl_str: &str) -> anyhow::Result<Vec<ExpressionAst>> {
        let (i, res) = routing_expr(expr_dsl_str)
            .finish()
            .map_err(|e| anyhow::anyhow!("error parsing routing expression: {e}"))?;
        eof::<_, ()>(i)?;

        Ok(res)
    }

    // tag, but ignore leading and trailing whitespaces
    pub fn wtag<'a, Error: nom::error::ParseError<&'a str>>(
        t: &'a str,
    ) -> impl Parser<&'a str, Output = &'a str, Error = Error> {
        delimited(multispace0, tag(t), multispace0)
    }

    // DSL:
    //
    // RoutingExpr := RoutingSubExpr [ , RoutingExpr ]
    // RougingSubExpr := Identifier [ \( Arguments \) ]
    // Identifier := FieldChar [ Identifier ]
    // FieldChar := { a..z | A..Z | 0..9 | _ | . | \ | / | @ | $ }

View on GitHub (pinned to a39730c5cd)