{"record":{"id":"c7e6307caff1ea84","repo":"quickwit-oss/tantivy","slug":"non-zero-packed-bits-fit-in-u64","errorCode":null,"errorMessage":"non-zero packed bits fit in u64","messagePattern":"non-zero packed bits fit in u64","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/aggregation/bucket/multi_terms/mod.rs","lineNumber":983,"sourceCode":"        packs.push(FieldPack {\n            shift,\n            mask,\n            min_value,\n            max_offset,\n        });\n        shift += width;\n    }\n    packs.reverse();\n    Some(packs)\n}\n\n#[inline]\nfn shift_packed_bits(bits: u64, shift: u32) -> u64 {\n    if bits == 0 {\n        0\n    } else {\n        bits.checked_shl(shift)\n            .expect(\"non-zero packed bits fit in u64\")\n    }\n}\n\nfn compute_max_packed(packs: &[FieldPack]) -> u64 {\n    packs.iter().fold(0u64, |packed, field| {\n        packed | shift_packed_bits(field.max_offset, field.shift)\n    })\n}\n\n#[derive(Clone, Debug)]\nstruct PackedU64KeyPacking {\n    packs: Vec<FieldPack>,\n}\n\n/// Selects the key packing and bucket storage, then boxes the concrete collector.\nfn build_multi_terms_collector<BucketSlot: BucketIdSlot>(\n    req: &mut AggregationsSegmentCtx,\n    node: &AggRefNode,","sourceCodeStart":965,"sourceCodeEnd":1001,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/src/aggregation/bucket/multi_terms/mod.rs#L965-L1001","documentation":"This is a Rust panic from an `expect` on `u64::checked_shl` inside `shift_packed_bits` in multi-terms aggregation. The function shifts a field's packed bits left by a computed shift amount, and the panic fires when `shift >= 64` (or bits would overflow), meaning the combined per-field bit offsets of the terms aggregation exceed the 64 bits available in a single packed key. The library assumes the sum of all field max_offsets stays within 64 bits; a mis-computed or corrupt pack layout violates that invariant.","triggerScenarios":"Calling a multi_terms aggregation whose per-field packed bit layout (`field.max_offset` + `field.shift`) exceeds 64 total bits, e.g. very high-cardinality or wide ordinal fields combined in one multi_terms agg, so `checked_shl(shift)` returns None and the expect panics.","commonSituations":"Multi-terms aggregation over many fields or fields with large term dictionaries where the sum of bit widths of all sub-fields overflows u64; index segments with unexpectedly large ordinals after mapping or index-version changes.","solutions":["Reduce the number of fields in the multi_terms aggregation so the combined bit width fits in 64 bits.","Check term/ordinal cardinality of the involved fields; split the aggregation or use a composite aggregation instead.","If you maintain the code, return a Result from shift_packed_bits and surface a user-facing error instead of expecting.","Reindex the field if a corrupt or oversized ordinal layout is suspected."],"exampleFix":"// before\nbits.checked_shl(shift).expect(\"non-zero packed bits fit in u64\")\n// after\nbits.checked_shl(shift)\n    .ok_or_else(|| crate::AggregationError::Internal(\"packed bits overflow u64\".to_string()))?","handlingStrategy":"validation","validationCode":"// Before issuing a multi_terms agg, bound the combined ordinal bit width of the fields.\nfn packed_bits_fit_in_u64(field_max_offsets: &[u64]) -> bool {\n    field_max_offsets.iter().map(|o| 64 - o.leading_zeros()).sum::<u32>() <= 64\n}\nif !packed_bits_fit_in_u64(&offsets) {\n    // fall back to a composite aggregation instead of multi_terms\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep the number of multi_terms sub-fields small enough that their ordinal bit widths fit in 64 bits.","Prefer composite aggregation for many-field grouping.","Monitor term dictionary cardinality for fields used in multi_terms."],"tags":["rust","panic","aggregation","overflow","integer-overflow"],"backgroundTag":"integer-overflow-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"}