{"record":{"id":"dbc6639fe23aa859","repo":"libnyanpasu/clash-nyanpasu","slug":"overlay-document-is-not-a-mapping-skipped","errorCode":null,"errorMessage":"overlay document is not a mapping, skipped","messagePattern":"overlay document is not a mapping, skipped","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"backend/nyanpasu-config/src/runtime/executor/overlay.rs","lineNumber":22,"sourceCode":"\nuse std::sync::Arc;\n\nuse crate::runtime::value::ConfigValue;\n\nuse super::{\n    artifact::StepLogEntry,\n    ports::ScriptRunner,\n    value_util::{deep_merge_value, get_at, parse_dotted_path, remove_at, replace_at},\n};\n\npub(super) fn apply_overlay(\n    overlay: &ConfigValue,\n    mut config: ConfigValue,\n    runner: &dyn ScriptRunner,\n    logs: &mut Vec<StepLogEntry>,\n) -> ConfigValue {\n    let Some(entries) = overlay.as_object_arc() else {\n        logs.push(StepLogEntry::warn(\n            \"overlay document is not a mapping, skipped\",\n        ));\n        return config;\n    };\n\n    // IndexMap iteration = document order (parity with Mapping iteration).\n    for (key, value) in entries.iter() {\n        // Legacy quirk kept verbatim (merge.rs:248): directive matching and\n        // the remainder path are lowercased; bare keys preserve case.\n        let lowered = key.to_ascii_lowercase();\n        if let Some(field) = strip_any(&lowered, &[\"prepend__\", \"prepend-\"]) {\n            config = splice_sequence(config, field, value, true, logs);\n        } else if let Some(field) = strip_any(&lowered, &[\"append__\", \"append-\"]) {\n            config = splice_sequence(config, field, value, false, logs);\n        } else if let Some(field) = lowered.strip_prefix(\"override__\") {\n            config = override_path(config, field, value, logs);\n        } else if let Some(field) = lowered.strip_prefix(\"filter__\") {\n            config = filter_path(config, field, value, runner, logs);","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/nyanpasu-config/src/runtime/executor/overlay.rs#L4-L40","documentation":"apply_overlay expects the overlay document to be a mapping (object) whose keys name config fields. If the parsed overlay value is not an object (list, scalar, null), the entire overlay is skipped with this warning rather than erroring, and the config is returned unmodified.","triggerScenarios":"apply_with → apply_overlay: overlay.as_object_arc() returns None because the overlay file/value deserialized to a non-mapping ConfigValue.","commonSituations":"An overlay file whose top level is a YAML list or a bare scalar; a mis-serialized overlay (e.g. saved as `[...]` instead of `{...}`); selecting the wrong file as an overlay; an overlay that failed parsing and fell back to a non-object default.","solutions":["Inspect the overlay document and wrap its content in a top-level mapping of field → operation","Validate the overlay parses to an object before applying","Re-export/re-save the overlay from the UI","Confirm the correct file is wired as the overlay input"],"exampleFix":"# before (overlay.yaml)\n- rules:\n    prepend: []\n# after\nrules:\n  prepend: []","handlingStrategy":"type-guard","validationCode":"fn overlay_is_mapping(overlay: &ConfigValue) -> bool { overlay.as_object_arc().is_some() }","typeGuard":"if !overlay_is_mapping(&overlay) { return Err(anyhow!(\"overlay must be a top-level mapping\")); }","tryCatchPattern":"let Some(entries) = overlay.as_object_arc() else {\n    return Err(anyhow!(\"overlay document is not a mapping\"));\n};","preventionTips":["Ensure overlay files have a top-level YAML/JSON object, not a list or scalar","Validate overlay serialization right after saving/exporting","Confirm the correct file is registered as an overlay before apply"],"tags":["config","overlay","schema"],"backgroundTag":"config-type-mismatch","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}