{"record":{"id":"1fc6868a12e77e5e","repo":"quickwit-oss/quickwit","slug":"concatenate-field-has-include-dynamic-fields-set","errorCode":null,"errorMessage":"concatenate field has `include_dynamic_fields` set, but index isn't dynamic","messagePattern":"concatenate field has `include_dynamic_fields` set, but index isn't dynamic","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-doc-mapper/src/doc_mapper/doc_mapper_impl.rs","lineNumber":194,"sourceCode":"        let document_size_field = if doc_mapping.store_document_size {\n            let document_size_field_options = tantivy::schema::NumericOptions::default().set_fast();\n            Some(\n                schema_builder.add_u64_field(DOCUMENT_SIZE_FIELD_NAME, document_size_field_options),\n            )\n        } else {\n            None\n        };\n        let source_field = if doc_mapping.store_source {\n            Some(schema_builder.add_json_field(SOURCE_FIELD_NAME, STORED))\n        } else {\n            None\n        };\n        let MappingNodeRoot {\n            field_mappings,\n            concatenate_dynamic_fields,\n        } = build_mapping_tree(&doc_mapping.field_mappings, &mut schema_builder)?;\n        if !concatenate_dynamic_fields.is_empty() && dynamic_field.is_none() {\n            bail!(\"concatenate field has `include_dynamic_fields` set, but index isn't dynamic\");\n        }\n        let timestamp_field_path = if let Some(timestamp_field_name) = &doc_mapping.timestamp_field\n        {\n            validate_timestamp_field(timestamp_field_name, &field_mappings)?;\n            Some(build_field_path_from_str(timestamp_field_name))\n        } else {\n            None\n        };\n        let schema = schema_builder.build();\n\n        let tokenizer_manager = create_default_quickwit_tokenizer_manager();\n        let mut custom_tokenizer_names = HashSet::new();\n        for tokenizer_config_entry in &doc_mapping.tokenizers {\n            if custom_tokenizer_names.contains(&tokenizer_config_entry.name) {\n                bail!(\n                    \"duplicated custom tokenizer: `{}`\",\n                    tokenizer_config_entry.name\n                );","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-doc-mapper/src/doc_mapper/doc_mapper_impl.rs#L176-L212","documentation":"During DocMapper construction (try_from), the mapping tree is built and may produce concatenate field mappings that include dynamic fields. If any such mapping exists but the index schema defines no dynamic field, construction is aborted. A concatenate field with `include_dynamic_fields: true` only makes sense when the index actually has a dynamic field to pull from.","triggerScenarios":"Calling `QuickwitDocMapper::try_from(index_config)` where the index config's doc_mapping contains a concatenate field entry with `include_dynamic_fields: true` while `doc_mapping.dynamic_field` is unset.","commonSituations":"Copy-pasting an index config that uses concatenate + dynamic fields from an example, then removing or renaming the dynamic field without removing `include_dynamic_fields: true` from the concatenate mapping.","solutions":["Add a `dynamic_field` entry to the doc_mapping so the index is dynamic.","Set `include_dynamic_fields: false` (or remove it) on the concatenate field.","Remove the concatenate field mapping if it is no longer needed."],"exampleFix":"# before\ndoc_mapping:\n  mode: lenient\n  concatenate:\n    body_concat:\n      fields: [body]\n      include_dynamic_fields: true\n\n# after\ndoc_mapping:\n  mode: lenient\n  dynamic_field: dynamic\n  concatenate:\n    body_concat:\n      fields: [body]\n      include_dynamic_fields: true","handlingStrategy":"validation","validationCode":"fn check_concatenate_dynamic(cfg: &serde_yaml::Value) -> Result<(), String> {\n    let has_dynamic = cfg[\"doc_mapping\"][\"dynamic_field\"].is_some();\n    let concat = &cfg[\"doc_mapping\"][\"concatenate\"];\n    if let Some(concat) = concat.as_mapping() {\n        for (_name, entry) in concat {\n            if entry[\"include_dynamic_fields\"].as_bool() == Some(true) && !has_dynamic {\n                return Err(\"concatenate uses include_dynamic_fields but no dynamic_field is set\".into());\n            }\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match QuickwitDocMapper::try_from(index_config) {\n    Ok(mapper) => mapper,\n    Err(e) if e.to_string().contains(\"include_dynamic_fields\") => {\n        eprintln!(\"Config error: add a dynamic_field or disable include_dynamic_fields: {e}\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Treat `include_dynamic_fields: true` as implying a dynamic_field must exist in the same doc_mapping.","Validate index configs with `quickwit index create --dry-run` style checks before deploy.","When removing a dynamic field, grep the config for `include_dynamic_fields`."],"tags":["config","index-schema","rust"],"backgroundTag":"schema-validation-failed","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}