{"record":{"id":"9a69fa38b432c664","repo":"quickwit-oss/tantivy","slug":"at-least-one-bound-must-be-set-9a69fa","errorCode":null,"errorMessage":"At least one bound must be set","messagePattern":"At least one bound must be set","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/range_query/range_query_fastfield.rs","lineNumber":64,"sourceCode":"\nimpl FastFieldRangeWeight {\n    /// Create a new FastFieldRangeWeight\n    pub fn new(bounds: BoundsRange<Term>) -> Self {\n        Self { bounds }\n    }\n}\n\nimpl Weight for FastFieldRangeWeight {\n    fn scorer(&self, reader: &SegmentReader, boost: Score) -> crate::Result<Box<dyn Scorer>> {\n        // Check if both bounds are Bound::Unbounded\n        if self.bounds.is_unbounded() {\n            return Ok(Box::new(AllScorer::new(reader.max_doc())));\n        }\n\n        let term = self\n            .bounds\n            .get_inner()\n            .expect(\"At least one bound must be set\");\n        let schema = reader.schema();\n        let field_type = schema.get_field_entry(term.field()).field_type();\n        assert_eq!(\n            term.typ(),\n            field_type.value_type(),\n            \"Field is of type {:?}, but got term of type {:?}\",\n            field_type,\n            term.typ()\n        );\n        let field_name = term.get_full_path(reader.schema());\n\n        let get_value_bytes = |term: &Term| term.value().value_bytes_payload();\n\n        let term_value = term.value();\n        if field_type.is_json() {\n            let bounds = self\n                .bounds\n                .map_bound(|term| term.value().as_json_value_bytes().unwrap().to_owned());","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/src/query/range_query/range_query_fastfield.rs#L46-L82","documentation":"RangeFastFieldWeight::scorer (src/query/range_query/range_query_fastfield.rs:64) unwraps bounds.get_inner() with \"At least one bound must be set\" to obtain the term carrying the field and type; with no bounds set the panic fires. Like the other range queries, a boundless range is considered an invalid query object and fails fast at scoring time (also reachable via explain()).","triggerScenarios":"Calling weight(...).scorer(...) or explain() on a fast-field range query whose RangeBounds never had lower_bound/upper_bound set; also hit from tests like test_range_regression_simplified when constructing the weight manually.","commonSituations":"Programmatic construction of fast-field range queries with both bound branches skipped; empty range objects from parsed/deserialized queries; copy-pasted builder code where setter calls were removed.","solutions":["Set at least one bound before executing or explaining the query.","Check bounds in the builder layer and return a user-facing error instead of building the query object.","For \"match everything\" semantics use the all-query or the documented unbounded range constructors rather than an empty range."],"exampleFix":"// before\nlet weight = fast_field_range_query.weight(...)?;\nlet scorer = weight.scorer(&reader, 1.0)?; // panics if bounds empty\n\n// after\nif bounds.lower_bound.is_none() && bounds.upper_bound.is_none() {\n    return Ok(Box::new(AllScorer::new(reader.max_doc()))); // or return Err(...)\n}\nlet scorer = weight.scorer(&reader, 1.0)?;","handlingStrategy":"validation","validationCode":"if bounds.lower_bound.is_none() && bounds.upper_bound.is_none() {\n    // fall back to AllScorer or return an error before scoring\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set at least one bound before weight()/scorer()/explain()","Unit-test dynamically constructed fast-field range queries","Use documented unbounded-range helpers, never empty bounds","Wrap user query building in validation returning Result"],"tags":["rust","panic","query","range-query","fast-fields"],"backgroundTag":"empty-range-bounds","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"}