{"record":{"id":"dd1eb2561fc67eeb","repo":"quickwit-oss/tantivy","slug":"support-only-up-to-u16-max-field-ids","errorCode":null,"errorMessage":"support only up to u16::MAX field ids","messagePattern":"support only up to u16::MAX field ids","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/schema/document/default_document.rs","lineNumber":143,"sourceCode":"    pub fn add_custom(&mut self, field: Field, value: &[u8]) {\n        self.add_leaf_field_value(field, ReferenceValueLeaf::Custom(value));\n    }\n\n    /// Add a dynamic object field\n    pub fn add_object(&mut self, field: Field, object: BTreeMap<String, OwnedValue>) {\n        self.add_field_value(field, &OwnedValue::from(object));\n    }\n\n    /// Add a (field, value) to the document.\n    ///\n    /// `OwnedValue` implements Value, which should be easiest to use, but is not the most\n    /// performant.\n    pub fn add_field_value<'a, V: Value<'a>>(&mut self, field: Field, value: V) {\n        let field_value = FieldValueAddr {\n            field: field\n                .field_id()\n                .try_into()\n                .expect(\"support only up to u16::MAX field ids\"),\n            value_addr: self.add_value(value),\n        };\n        self.field_values.push(field_value);\n    }\n\n    /// Add a (field, leaf value) to the document.\n    /// Leaf values don't have nested values.\n    pub fn add_leaf_field_value<'a, T: Into<ReferenceValueLeaf<'a>>>(\n        &mut self,\n        field: Field,\n        typed_val: T,\n    ) {\n        let value = typed_val.into();\n        let field_value = FieldValueAddr {\n            field: field\n                .field_id()\n                .try_into()\n                .expect(\"support only up to u16::MAX field ids\"),","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/src/schema/document/default_document.rs#L125-L161","documentation":"This panic comes from `Document::add_field_value` in tantivy's default document implementation. Each (field, value) pair is stored in a compact `FieldValueAddr` struct where the field id is packed into a `u16` to keep the document representation memory-efficient. If the schema assigns the field an id greater than `u16::MAX` (65535), the `try_into::<u16>()` conversion fails and the `.expect` panics.","triggerScenarios":"Calling `Document::add_field_value(field, value)` (or any higher-level `add_*(field, value)` convenience such as `add_text`, `add_u64`, `add_date`) with a `Field` whose id exceeds 65535, i.e. a schema with more than 65536 fields.","commonSituations":"Programmatically generating a schema with hundreds of thousands of fields (e.g. one field per key in user-supplied JSON), building a schema from unbounded/log-columnar data, or reusing/multiplexing indexes across tenants where field ids grow unchecked.","solutions":["Check the schema size before indexing: ensure the number of fields added to `SchemaBuilder` stays at or below 65536 and fail early with a clear application-level error.","Remap high-cardinality keys to a smaller set of schema fields, storing the original key inside a JSON/text field instead of creating one schema field per key.","If you genuinely need >65535 fields, split the data across multiple indexes/schemas so each schema stays under the limit.","Wrap document construction in `catch_unwind` only as a last resort; this is a hard limit of the format, not a recoverable condition."],"exampleFix":"// before: one field per JSON key, blows past u16::MAX\nfor key in json_keys { schema_builder.add_text_field(key, TEXT); }\n\n// after: bounded schema + dynamic key stored in a single field\nlet dynamic = schema_builder.add_json_field(\"attributes\", STORED);\nlet mut doc = Document::default();\ndoc.add_field_value(dynamic, serde_json::to_value(json_obj)?);","handlingStrategy":"validation","validationCode":"fn validate_schema(schema: &tantivy::schema::Schema) -> Result<(), String> {\n    if schema.num_fields() > (u16::MAX as usize) + 1 {\n        return Err(format!(\n            \"schema has {} fields; tantivy supports at most {} field ids (u16::MAX)\",\n            schema.num_fields(),\n            u16::MAX\n        ));\n    }\n    Ok(())\n}\nvalidate_schema(&schema)?;","typeGuard":"fn field_id_fits_u16(field: &tantivy::schema::Field) -> bool {\n    (field.field_id() as usize) <= u16::MAX as usize\n}","tryCatchPattern":"// expect() panics, not Result: isolate doc construction\nlet doc = std::panic::catch_unwind(|| {\n    let mut doc = Document::default();\n    doc.add_field_value(field, value);\n    doc\n})\n.map_err(|_| anyhow::anyhow!(\"field id exceeds u16::MAX limit\"))?;","preventionTips":["Enforce a hard schema field-count budget (< 65536) in schema-building code and CI tests","Store dynamic/high-cardinality keys in a single JSON field instead of one field per key","Assert `field.field_id() <= u16::MAX` in any wrapper that accepts a Field argument"],"tags":["schema","panic","field-limit","indexing"],"backgroundTag":"field-id-overflow","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"}