{"record":{"id":"28892a6d63b908a7","repo":"jdx/mise","slug":"bootstrap-files-present-files-require-sour","errorCode":null,"errorMessage":"[bootstrap.files].\"{}\": present files require source or content","messagePattern":"\\[bootstrap\\.files\\]\\.\"(.+?)\": present files require source or content","errorType":"validation","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/managed_files.rs","lineNumber":612,"sourceCode":"        let mut content = match (config.source, config.content, config.state) {\n            (Some(_), Some(_), _) => {\n                bail!(\n                    \"[bootstrap.files].\\\"{}\\\": source and content are mutually exclusive\",\n                    path.display()\n                )\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, &origin.config))\n                .transpose()\n                .wrap_err_with(|| {\n                    format!(\n                        \"[bootstrap.files].\\\"{}\\\": failed to render template\",\n                        path.display()","sourceCodeStart":594,"sourceCodeEnd":630,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/managed_files.rs#L594-L630","documentation":"During ManagedFile construction, a file declared with state = \"present\" must say what its body should be: from_toml requires either source or content and bails when both are None. Absent-state files legitimately have no body, so the requirement applies only to Present files.","triggerScenarios":"Parsing a [bootstrap.files] entry whose match arm is (None, None, ManagedState::Present) — i.e. neither `source` nor `content` set while state = \"present\".","commonSituations":"Adding a file entry as a placeholder before filling in its body; deleting the content key when switching to a source but forgetting to add the source; a state defaulting to present after removing an explicit absent declaration.","solutions":["Add a `content` string with the desired file body.","Or add a `source` path pointing to the file/template to copy.","Or set state = \"absent\" if the file only needs to be removed."],"exampleFix":"# before\n[bootstrap.files.\"/etc/app.conf\"]\nstate = \"present\"\n\n# after\n[bootstrap.files.\"/etc/app.conf\"]\ncontent = \"key = value\"\nstate = \"present\"","handlingStrategy":"validation","validationCode":"// rust\nfn validate_body(entry: &FileEntry) -> Result<(), &'static str> {\n    if entry.state == State::Present && entry.source.is_none() && entry.content.is_none() {\n        return Err(\"present files require source or content\");\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never add a present-state file entry without its body in the same commit.","Use a typed builder that requires body for Present and rejects it for Absent.","Grep the TOML for `state = \"present\"` entries lacking content/source during review."],"tags":["config-validation","managed-files","missing-required-field"],"backgroundTag":"missing-required-config-field","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}