{"record":{"id":"6d3a2cc9654c0846","repo":"wasmerio/wasmer","slug":"could-not-parse-yaml-semantically-e","errorCode":null,"errorMessage":"could not parse YAML semantically: {e}","messagePattern":"could not parse YAML semantically: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/cli/src/utils/yaml.rs","lineNumber":55,"sourceCode":"        Err(err) => {\n            tracing::warn!(\n                ?err,\n                \"cannot format-preserve app YAML edit; \\\n                 rewriting the file without preserving formatting\"\n            );\n            Ok(serde_yaml::to_string(target)?)\n        }\n    }\n}\n\nfn try_format_preserving_edit(text: &str, target: &Value) -> anyhow::Result<String> {\n    let doc = Document::from_str(text)\n        .map_err(|e| anyhow::anyhow!(\"could not parse YAML for format-preserving edit: {e}\"))?;\n    // Second parse, used to detect which keys changed. `yaml_edit` node text\n    // cannot be reparsed for this: it is dedented on the first line only, so\n    // block values are not valid standalone YAML.\n    let original: Value = serde_yaml::from_str(text)\n        .map_err(|e| anyhow::anyhow!(\"could not parse YAML semantically: {e}\"))?;\n\n    match (doc.as_mapping(), target, &original) {\n        (Some(mapping), Value::Mapping(target_mapping), Value::Mapping(original_mapping)) => {\n            merge_into_mapping(&mapping, target_mapping, Some(original_mapping), true)?;\n            let out = doc.to_string();\n            // Restore the leading comment block that `yaml_edit` drops (see\n            // `leading_trivia`).\n            let header = leading_trivia(text);\n            if !header.is_empty() && !out.starts_with(header) {\n                Ok(format!(\"{header}{out}\"))\n            } else {\n                Ok(out)\n            }\n        }\n        // The document root is not a mapping (or the target is not a mapping).\n        // We have no formatting to preserve in a meaningful way, so fall back to\n        // a plain serialization of the target.\n        _ => Ok(serde_yaml::to_string(target)?),","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/wasmerio/wasmer/blob/8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5/lib/cli/src/utils/yaml.rs#L37-L73","documentation":"try_format_preserving_edit performs a second, semantic parse with serde_yaml so it can detect which keys changed (yaml_edit's node text can't be reparsed because block values are only dedented on the first line). If the syntax was valid to yaml_edit but serde_yaml rejects the value model (rare deserialization/type incompatibilities) this error is thrown.","triggerScenarios":"Document::from_str succeeded but serde_yaml::from_str::<Value> failed — typically documents with YAML features serde_yaml cannot represent into a Value mapping here, or edge-case incompatibility between the yaml_edit and serde_yaml parsers on the same text.","commonSituations":"Config files using exotic YAML constructs (complex mapping keys like `? [a, b]`, unusual anchors/aliases, multiple documents `---` in one file) where the two parsers disagree; a serde_yaml version change altering accepted syntax.","solutions":["Simplify the YAML: remove multiple documents, complex keys, or anchors/aliases that a strict parser may reject.","Check the inner `{e}` from serde_yaml for the exact deserialization complaint and fix that construct.","Ensure serde_yaml and yaml_edit crate versions are compatible (update the CLI to the latest release).","Reformat block values into standard flow/block style that both parsers handle identically.","As a workaround, apply the config change manually in the file instead of via format-preserving edit."],"exampleFix":"// before (complex key serde_yaml may reject)\n? [debug, verbose]\n: true\n// after\ndebug_verbose: true","handlingStrategy":"validation","validationCode":"// ensure the document is a single, simple mapping both parsers accept\nfn validate_simple_yaml(path: &Path) -> anyhow::Result<()> {\n    let text = std::fs::read_to_string(path)?;\n    anyhow::ensure!(text.matches(\"---\").count() <= 1, \"multi-document YAML not supported\");\n    anyhow::ensure!(!text.contains(\"? \"), \"complex mapping keys not supported\");\n    let v: serde_yaml::Value = serde_yaml::from_str(&text)?;\n    anyhow::ensure!(v.is_mapping(), \"top level must be a mapping\");\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match apply_app_config_to_yaml(&text, &cfg) {\n    Ok(out) => out,\n    Err(e) if e.to_string().contains(\"could not parse YAML semantically\") => {\n        eprintln!(\"Simplify YAML constructs (anchors, complex keys, multi-docs): {e}\");\n        std::process::exit(1);\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Keep app config YAML to plain key/value mappings","Avoid multiple documents (---) in one config file","Pin and update CLI versions together with serde_yaml/yaml_edit fixes","Round-trip the file through a parser in CI to catch parser-compat regressions"],"tags":["rust","yaml","serde","parsing","config"],"backgroundTag":"yaml-parse-error","analyzedSha":"8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5","analyzedAt":"2026-09-01T23:06:31.009Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}