quickwit-oss/quickwit · error

error parsing key expression: {e}

Error message

error parsing key expression: {e}

What it means

Field names inside routing expressions are parsed as a dot-separated list of escaped keys. If a key segment is malformed (illegal characters, trailing dot, bad escape), the nom parser fails and the error is wrapped with this message. It is a sub-step of parsing routing/partitioning expressions.

Source

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

    /// Parse a single path component, separated by dots. De-escape any escaped dot it may contain.
    fn escaped_key(input: &str) -> IResult<&str, Cow<'_, str>> {
        map(escaped(key_identifier, '\\', tag(".")), |s: &str| {
            if s.contains("\\.") {
                Cow::Owned(s.replace("\\.", "."))
            } else {
                Cow::Borrowed(s)
            }
        })
        .parse(input)
    }

    /// Parse a field name into a path, de-escaping where appropriate.
    pub(crate) fn parse_field_name(input: &str) -> anyhow::Result<Vec<Cow<'_, str>>> {
        let (i, res) = separated_list0(tag("."), escaped_key)
            .parse(input)
            .finish()
            .map_err(|e| anyhow::anyhow!("error parsing key expression: {e}"))?;
        eof::<_, ()>(i)?;
        Ok(res)
    }
}

#[cfg(test)]
mod tests {
    use std::collections::HashSet;

    use super::*;

    #[track_caller]
    fn test_ser_deser(expr: &InnerRoutingExpr) {
        let ser = expr.to_string();
        assert_eq!(&InnerRoutingExpr::from_str(&ser).unwrap(), expr);
    }

    #[track_caller]

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Fix the key per the wrapped error: escape special characters (e.g. literal dots) with backslashes.
  2. Remove empty segments such as double dots or a trailing dot.
  3. Use the exact field name as defined in the index mapping, with proper escaping.
  4. If the field name is unmanageable, rename the field in the mapping to an identifier-safe name.

Example fix

// before
"tenant.id"
// after
"tenant\\.id"
Defensive patterns

Strategy: validation

Validate before calling

fn valid_key(k: &str) -> bool {
    !k.is_empty() && !k.starts_with('.') && !k.ends_with('.') && !k.contains("..")
}
// ensure every dot-separated segment passes valid_key

Try / catch

match parse_field_name(input) {
    Err(e) if e.to_string().contains("error parsing key expression") => {
        // escape or correct the field-name key
    }
    r => r?,
}

Prevention

When it happens

Trigger: `parse_field_name` receives a key string from a routing expression containing an invalid key: an unescaped special character, an empty segment (e.g. `a..b` or trailing `.`), or a malformed escape sequence.

Common situations: Field names containing dots not escaped with backslash, accidental whitespace or punctuation in the partitioning key path, or auto-generated expressions from field names with unusual characters.

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/f8832a641aef4ebc. Report an issue: GitHub.