{"record":{"id":"d67e8d06c6c72b4a","repo":"jdx/mise","slug":"bootstrap-files-absent-files-must-not-decl","errorCode":null,"errorMessage":"[bootstrap.files].\"{}\": absent files must not declare source or content","messagePattern":"\\[bootstrap\\.files\\]\\.\"(.+?)\": absent files must not declare source or content","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/managed_files.rs","lineNumber":557,"sourceCode":"                )\n            }\n            (Some(source), None, ManagedState::Present) => {\n                let source = resolve_source_path(base, &source);\n                Some(fs::read_to_string(&source).wrap_err_with(|| {\n                    format!(\n                        \"[bootstrap.files].\\\"{}\\\": failed to read source {}\",\n                        path.display(),\n                        source.display()\n                    )\n                })?)\n            }\n            (None, Some(content), ManagedState::Present) => Some(content),\n            (None, None, ManagedState::Present) => bail!(\n                \"[bootstrap.files].\\\"{}\\\": present files require source or content\",\n                path.display()\n            ),\n            (None, None, ManagedState::Absent) => None,\n            (_, _, ManagedState::Absent) => bail!(\n                \"[bootstrap.files].\\\"{}\\\": absent files must not declare source or content\",\n                path.display()\n            ),\n        };\n        if config.template {\n            let rendered = content\n                .as_deref()\n                .map(|content| secrets.render(root_config, content, base, &path))\n                .transpose()\n                .wrap_err_with(|| {\n                    format!(\n                        \"[bootstrap.files].\\\"{}\\\": failed to render template\",\n                        path.display()\n                    )\n                })?;\n            content = rendered;\n        }\n        Ok(Self {","sourceCodeStart":539,"sourceCodeEnd":575,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/managed_files.rs#L539-L575","documentation":"Raised by ManagedFileRequest::from_toml when a [bootstrap.files] entry declares state=\"absent\" but also supplies `source` or `content`. Deletion only needs the path; providing a body for a file the library is asked to remove is contradictory, so the entry is rejected at parse time.","triggerScenarios":"Parsing a [bootstrap.files.\"<path>\"] TOML entry with state = \"absent\" where `source` and/or `content` is set — the (_, _, ManagedState::Absent) catch-all arm after the (None, None, Absent) case.","commonSituations":"Duplicating an existing present-file block and changing only state to \"absent\" without removing the body keys; a cleanup entry written by copying a template config that always includes `content`; bulk-generating entries where absent/present is data-driven and body keys leak into absent ones.","solutions":["Remove the `source` and `content` keys from the absent-state entry, keeping only path and state.","If you actually want the file to exist with that body, set state = \"present\" instead.","Re-run bootstrap to confirm the config parses."],"exampleFix":"# before\n[[bootstrap.files]]\npath = \"/etc/legacy.conf\"\ncontent = \"old settings\"\nstate = \"absent\"\n\n# after\n[[bootstrap.files]]\npath = \"/etc/legacy.conf\"\nstate = \"absent\"","handlingStrategy":"validation","validationCode":"fn validate_file_entry(entry: &ManagedFileTomlConfig) -> Result<(), String> {\n    if entry.state == ManagedState::Absent && (entry.source.is_some() || entry.content.is_some()) {\n        return Err(\"absent files must not declare source or content\".into());\n    }\n    Ok(())\n}","typeGuard":"fn absent_with_body(entry: &ManagedFileTomlConfig) -> bool {\n    entry.state == ManagedState::Absent && (entry.source.is_some() || entry.content.is_some())\n}","tryCatchPattern":null,"preventionTips":["Absent entries should contain only path, state (and removal flags) — no body keys.","When duplicating a present entry to make an absent one, strip `source`/`content`.","Lint generated configs to reject body keys on absent entries."],"tags":["config","toml","bootstrap","validation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}