{"record":{"id":"3d48e36ecea4c678","repo":"vectordotdev/vector","slug":"unsupported-yaml-merge-key","errorCode":null,"errorMessage":"UNSUPPORTED_YAML_MERGE_KEY","messagePattern":"UNSUPPORTED_YAML_MERGE_KEY","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"vdev/src/utils/features.rs","lineNumber":127,"sourceCode":"}\n\npub fn load_and_extract(filename: &Path) -> Result<Vec<String>> {\n    let config = fs::read_to_string(filename)\n        .with_context(|| format!(\"failed to read {}\", filename.display()))?;\n\n    let config: FeatureConfig = match filename\n        .extension()\n        .and_then(OsStr::to_str)\n        .map(str::to_lowercase)\n        .as_deref()\n    {\n        None => bail!(\"Invalid filename {}, no extension\", filename.display()),\n        Some(\"json\") => serde_json::from_str(&config)?,\n        Some(\"toml\") => toml::from_str(&config)?,\n        Some(\"yaml\" | \"yml\") => {\n            let value: serde_yaml::Value = serde_yaml::from_str(&config)?;\n            if contains_yaml_merge_key(&value) {\n                bail!(UNSUPPORTED_YAML_MERGE_KEY);\n            }\n            serde_yaml::from_value(value)?\n        }\n        Some(_) => bail!(\"Invalid filename {}, unknown extension\", filename.display()),\n    };\n\n    let declared_features = CargoToml::load_from(&find_repo_root()?.join(\"Cargo.toml\"))?\n        .features\n        .into_keys()\n        .collect();\n\n    from_config(&config, &declared_features)\n}\n\nfn contains_yaml_merge_key(value: &serde_yaml::Value) -> bool {\n    match value {\n        serde_yaml::Value::Sequence(values) => values.iter().any(contains_yaml_merge_key),\n        serde_yaml::Value::Mapping(mapping) => mapping","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/vectordotdev/vector/blob/bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013/vdev/src/utils/features.rs#L109-L145","documentation":"When parsing a YAML feature config, load_and_extract scans the deserialized serde_yaml::Value for merge keys (`<<:` or `<<-`). serde_yaml does not resolve YAML merge keys into the target struct, so configs relying on them would silently lose fields; the tool proactively bails with the UNSUPPORTED_YAML_MERGE_KEY message rather than produce wrong feature lists.","triggerScenarios":"Calling load_and_extract on a .yaml/.yml file whose mapping (at any nesting depth) contains a `<<:` merge key, typically used with YAML anchors to share component options.","commonSituations":"Copying a Kubernetes-style YAML config that uses anchors-and-merge-keys DRY patterns into a Vector feature config; refactoring shared sink settings with `<<: *defaults`.","solutions":["Remove the merge key and inline the merged fields explicitly","Resolve the anchors manually: replace `<<: *base` with the full copied key/value pairs","Rewrite the file in TOML or JSON, which have no merge-key semantics"],"exampleFix":"// before\nsinks:\n  my_sink:\n    <<: *common\n    type: console\n// after\nsinks:\n  my_sink:\n    type: console\n    inputs: [\"*\"]\n    encoding: json","handlingStrategy":"validation","validationCode":"fn uses_merge_key(yaml_text: &str) -> bool {\n    yaml_text.lines().any(|l| l.trim_start().starts_with(\"<<:\"))\n}\nif uses_merge_key(&text) { panic!(\"resolve YAML merge keys before processing\"); }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid `<<:` merge keys in Vector feature configs; inline shared fields","Prefer TOML or JSON for configs generated by scripts","When copying YAML from Kubernetes/Helm, expand anchors first"],"tags":["rust","yaml","validation","unsupported-feature"],"backgroundTag":"unsupported-config-value","analyzedSha":"bdb87aeaa4c4ff27c0ba643c1c77b21bf2ef4013","analyzedAt":"2026-09-16T02:53:35.741Z","contentChangedAt":"2026-09-16T02:53:35.741Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}