{"record":{"id":"0f007f78d1590a4e","repo":"quickwit-oss/tantivy","slug":"field-already-exists-in-schema","errorCode":null,"errorMessage":"Field already exists in schema {}","messagePattern":"Field already exists in schema (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/schema/schema.rs","lineNumber":221,"sourceCode":"    pub fn add_custom_field<T: Into<String>>(\n        &mut self,\n        field_name: &str,\n        type_name: T,\n        params: serde_json::Value,\n    ) -> Field {\n        let field_entry = FieldEntry::new_custom(\n            field_name.to_string(),\n            CustomOptions::new(type_name, params),\n        );\n        self.add_field(field_entry)\n    }\n\n    /// Adds a field entry to the schema in build.\n    pub fn add_field(&mut self, field_entry: FieldEntry) -> Field {\n        let field = Field::from_field_id(self.fields.len() as u32);\n        let field_name = field_entry.name().to_string();\n        if let Some(_previous_value) = self.fields_map.insert(field_name, field) {\n            panic!(\"Field already exists in schema {}\", field_entry.name());\n        };\n        self.fields.push(field_entry);\n        field\n    }\n\n    /// Finalize the creation of a `Schema`\n    /// This will consume your `SchemaBuilder`\n    pub fn build(self) -> Schema {\n        Schema(Arc::new(InnerSchema {\n            fields: self.fields,\n            fields_map: self.fields_map,\n        }))\n    }\n}\n#[derive(Debug)]\nstruct InnerSchema {\n    fields: Vec<FieldEntry>,\n    fields_map: HashMap<String, Field>, // transient","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/quickwit-oss/tantivy/blob/b5d8deb80c26924e6b007a5b1a7630f35ca64de4/src/schema/schema.rs#L203-L239","documentation":"SchemaBuilder::add_field registers each field name uniquely in the schema's field map. Adding a field whose name already exists in the schema panics with 'Field already exists in schema <name>'. Field names are the primary lookup key, so duplicates are treated as a programming error rather than a recoverable error.","triggerScenarios":"Calling SchemaBuilder::add_field (or any of add_u64_field/add_i64_field/add_f64_field/add_bool_field/add_date_field/add_ip_addr_field) with a field_entry whose name was already added to the builder in the current build.","commonSituations":"Programmatically building a schema from config where a field is listed twice (e.g. defaults plus user overrides both defining 'timestamp'); merging field lists from multiple sources; loops that re-add the same field name; loading a saved JSON schema and re-adding defaults on top.","solutions":["De-duplicate field definitions before building: keep a HashSet of names and skip already-added ones.","Check the builder's existing names first (e.g. via a helper on Schema/schema fields) before each add_*_field call.","If merging schemas/configs, prefer explicit override semantics: replace the existing entry instead of adding a duplicate."],"exampleFix":"// before\nbuilder.add_u64_field(\"timestamp\", Indexed);\nbuilder.add_date_field(\"timestamp\", Indexed); // panics\n// after\nlet mut seen = HashSet::new();\nif seen.insert(\"timestamp\".to_string()) {\n    builder.add_date_field(\"timestamp\", Indexed);\n}","handlingStrategy":"validation","validationCode":"let mut names = HashSet::new();\nif !names.insert(field_entry.name().to_string()) {\n    return Err(format!(\"duplicate field: {}\", field_entry.name()));\n}\nbuilder.add_field(field_entry);","typeGuard":null,"tryCatchPattern":"// panic on duplicate name; guard before adding\nassert!(!existing_names.contains(field_name), \"duplicate schema field: {field_name}\");","preventionTips":["Track added field names in a HashSet while building schemas","De-duplicate fields when merging config-driven field lists","When loading saved schemas, don't re-add default fields on top","Centralize schema construction in one function to avoid scattered adds"],"tags":["panic","schema","duplicate-field","configuration"],"backgroundTag":"duplicate-schema-field","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"}