{"record":{"id":"48a1be88432f1ff1","repo":"quickwit-oss/tantivy","slug":"the-term-has-an-invalid-type-code","errorCode":null,"errorMessage":"The term has an invalid type code","messagePattern":"The term has an invalid type code","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/schema/term.rs","lineNumber":324,"sourceCode":"where B: AsRef<[u8]>\n{\n    /// Wraps a object holding bytes\n    pub fn wrap(data: B) -> ValueBytes<B> {\n        ValueBytes(data)\n    }\n\n    /// Wraps a object holding Vec<u8>\n    pub fn to_owned(&self) -> ValueBytes<Vec<u8>> {\n        ValueBytes(self.0.as_ref().to_vec())\n    }\n\n    fn typ_code(&self) -> u8 {\n        self.0.as_ref()[0]\n    }\n\n    /// Return the type of the term.\n    pub fn typ(&self) -> Type {\n        Type::from_code(self.typ_code()).expect(\"The term has an invalid type code\")\n    }\n\n    /// Returns the `u64` value stored in a term.\n    ///\n    /// Returns `None` if the term is not of the u64 type, or if the term byte representation\n    /// is invalid.\n    pub fn as_u64(&self) -> Option<u64> {\n        self.get_fast_type::<u64>()\n    }\n\n    fn get_fast_type<T: FastValue>(&self) -> Option<T> {\n        if self.typ() != T::to_type() {\n            return None;\n        }\n        let value_bytes = self.raw_value_bytes_payload();\n        let value_u64 = u64::from_be_bytes(value_bytes.try_into().ok()?);\n        Some(T::from_u64(value_u64))\n    }","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/src/schema/term.rs#L306-L342","documentation":"`Term::typ()` reads the first byte of the term's raw byte representation as a type code and converts it with `Type::from_code`, panicking via `expect(\"The term has an invalid type code\")` if the byte is not a known code. `Type::from_code` only recognizes the codes defined in `type_codes` (TEXT=0, U64=1, etc.), so any term whose leading byte falls outside that set triggers the panic. Many accessors (`get_fast_type`, `as_str`, `as_facet`, `as_bytes`, `as_ip_addr`, `as_json`) call `typ()` and inherit this panic.","triggerScenarios":"Constructing a `Term` from raw bytes with an invalid leading byte (e.g. `Term::wrap(term_bytes)` or manual byte-level term building), deserializing a corrupt term from an index segment, or offsetting/scrambling term bytes so byte 0 is not a valid type code.","commonSituations":"Reading an index written by an incompatible tantivy version (type-code layout changed), hand-crafted terms in tests/plugins using `Term::from` on misordered byte buffers, index corruption from partial writes, or custom code that prepends a value to the term without the type-code prefix.","solutions":["Validate the first byte of any manually built term against the valid `type_codes` before calling `typ()` or the dependent accessors.","Rebuild the index with the same tantivy version that wrote it — a version mismatch in term encoding is the most common cause of corrupt type codes.","Check index integrity; if terms come from disk (termdict/PostingFormat), re-index the segment since the data is corrupt.","Instead of `typ()`, use `value_bytes()` and interpret bytes yourself, or wrap calls in `catch_unwind` if processing untrusted term bytes."],"exampleFix":"// before: bytes pushed without type-code prefix\nlet mut term = Term::from_field_u64(field, 0);\nterm.as_bytes_mut().insert(0, 0xEE); // invalid code\n\n// after: build terms through typed constructors only\nlet term = Term::from_field_u64(field, 42);\nlet t = term.typ(); // always a valid Type","handlingStrategy":"type-guard","validationCode":"const VALID_TYPE_CODES: &[u8] = &[0u8, 1, 2, 3, 4, 5, 6, 7]; // TEXT, U64, I64, F64, DATE, FACET, BYTES, JSON codes\nfn term_has_valid_type_code(term: &Term) -> bool {\n    let bytes = term.value_bytes();\n    !bytes.is_empty() && VALID_TYPE_CODES.contains(&bytes[0])\n}","typeGuard":"fn safe_typ(term: &Term) -> Option<Type> {\n    let code = *term.value_bytes().first()?;\n    Type::from_code(code)\n}","tryCatchPattern":"let typ = std::panic::catch_unwind(|| term.typ())\n    .ok()\n    .or_else(|| safe_typ(&term))\n    .ok_or_else(|| anyhow::anyhow!(\"term has invalid type code: {:?}\", term.value_bytes().first()))?;","preventionTips":["Build terms only via typed constructors (Term::from_field_u64, from_field_text, ...) — never hand-assemble byte buffers","Do not mix terms across tantivy versions; term encoding is not cross-version stable","Run index integrity checks before reading terms from disk"],"tags":["panic","term","corruption","encoding"],"backgroundTag":"invalid-term-type-code","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"}