{"record":{"id":"b21d0d7ec7c7e2ab","repo":"quickwit-oss/tantivy","slug":"exist-query-without-a-field-isn-t-allowed","errorCode":null,"errorMessage":"Exist query without a field isn't allowed","messagePattern":"Exist query without a field isn't allowed","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"query-grammar/src/user_input_ast.rs","lineNumber":51,"sourceCode":"    pub(crate) fn set_field(self, field: Option<String>) -> Self {\n        match self {\n            UserInputLeaf::Literal(mut literal) => {\n                literal.field_name = field;\n                UserInputLeaf::Literal(literal)\n            }\n            UserInputLeaf::All => UserInputLeaf::All,\n            UserInputLeaf::Range {\n                field: _,\n                lower,\n                upper,\n            } => UserInputLeaf::Range {\n                field,\n                lower,\n                upper,\n            },\n            UserInputLeaf::Set { field: _, elements } => UserInputLeaf::Set { field, elements },\n            UserInputLeaf::Exists { field: _ } => UserInputLeaf::Exists {\n                field: field.expect(\"Exist query without a field isn't allowed\"),\n            },\n            UserInputLeaf::Regex { field: _, pattern } => UserInputLeaf::Regex { field, pattern },\n        }\n    }\n\n    pub(crate) fn set_default_field(&mut self, default_field: String) {\n        match self {\n            UserInputLeaf::Literal(literal) if literal.field_name.is_none() => {\n                literal.field_name = Some(default_field)\n            }\n            UserInputLeaf::All => {\n                *self = UserInputLeaf::Exists {\n                    field: default_field,\n                }\n            }\n            UserInputLeaf::Range { field, .. } if field.is_none() => *field = Some(default_field),\n            UserInputLeaf::Set { field, .. } if field.is_none() => *field = Some(default_field),\n            UserInputLeaf::Regex { field, .. } if field.is_none() => *field = Some(default_field),","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/query-grammar/src/user_input_ast.rs#L33-L69","documentation":"This is a panic (expect) inside UserInputLeaf's field-setting transformation: when transforming an Exists leaf with a field, the field Option is expected to be Some. An Exists query without a field is considered a programmer error by the query-grammar layer, so it panics rather than returning Result. It fires because the caller forgot to set a default field before this transformation.","triggerScenarios":"Calling the field-assigning method on a UserInputAst containing UserInputLeaf::Exists with field == None, i.e. after parsing something like _exists: without having set a default field via set_default_field or equivalent.","commonSituations":"Building query ASTs programmatically and forgetting to assign the default field; query parsers that pass user input straight through where the default field was never configured; writing tests/transforms over parsed leaves.","solutions":["Ensure a default field is set (set_default_field) before transforming/normalizing the AST.","Construct Exists leaves with a field always present, or validate the AST before transforming it.","If you control parsing, return a user-facing parse/validation error instead of reaching the expect: check field.is_some() beforehand.","Never let end-user input reach this transform without the default-field configuration step."],"exampleFix":"// before\nlet leaf = UserInputLeaf::Exists { field: None };\nleaf.with_field(...) // panics\n// after\nif leaf_field.is_some() {\n    leaf.with_field(...)\n} else {\n    return Err(QueryParserError::FieldDoesNotExist(\"_exists requires a field\"));\n}","handlingStrategy":"validation","validationCode":"// Validate before transforming the AST\nfn ensure_fields_set(ast: &UserInputAst) -> Result<(), &'static str> {\n    if let UserInputAst::Leaf(leaf) = ast {\n        if let UserInputLeaf::Exists { field } = leaf {\n            if field.is_none() { return Err(\"_exists leaf requires a field\"); }\n        }\n    }\n    Ok(())\n}","typeGuard":"fn has_field(leaf: &UserInputLeaf) -> bool {\n    !matches!(leaf, UserInputLeaf::Exists { field: None })\n}","tryCatchPattern":"// This is a panic, not a Result: prevent it, and if wrapping, isolate the transform\nlet result = std::panic::catch_unwind(|| {\n    ast.with_field(default_field)\n});","preventionTips":["Always call set_default_field before AST normalization","Never forward raw user input without default-field configuration","Prefer constructing Exists leaves with explicit fields","Add unit tests for Exists leaves without fields"],"tags":["rust","panic","query-parser","query-grammar"],"backgroundTag":"missing-required-field-panic","analyzedSha":"b5d8deb80c26924e6b007a5b1a7630f35ca64de4","analyzedAt":"2026-09-05T13:20:51.521Z","contentChangedAt":"2026-09-05T13:20:51.521Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}