{"record":{"id":"5833d3104650fc11","repo":"jdx/mise","slug":"present-file-has-content","errorCode":null,"errorMessage":"present file has content","messagePattern":"present file has content","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/managed_files.rs","lineNumber":673,"sourceCode":"    }\n\n    fn operation(&self) -> Result<Option<PrivilegedAction>> {\n        match self.plan()?.action {\n            ResourceAction::Noop => return Ok(None),\n            ResourceAction::Unknown if self.state == ManagedState::Absent => bail!(\n                \"refusing to remove directory {} as a file; declare it in [bootstrap.directories]\",\n                self.path.display()\n            ),\n            ResourceAction::Unknown => bail!(\n                \"refusing to replace non-file path {}; set replace = true to allow replacement\",\n                self.path.display()\n            ),\n            _ => {}\n        }\n        Ok(Some(match self.state {\n            ManagedState::Present => PrivilegedAction::WriteFile {\n                path: self.path.clone(),\n                content: self.content.clone().expect(\"present file has content\"),\n                owner: self.owner.clone(),\n                group: self.group.clone(),\n                mode: self.mode,\n                replace: self.replace,\n            },\n            ManagedState::Absent => PrivilegedAction::RemoveFile {\n                path: self.path.clone(),\n            },\n        }))\n    }\n}\n\nfn resolve_source_path(base: &Path, source: &str) -> PathBuf {\n    let source = if source.starts_with(\"~/\") {\n        crate::file::replace_path(source)\n    } else {\n        PathBuf::from(source)\n    };","sourceCodeStart":655,"sourceCodeEnd":691,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/managed_files.rs#L655-L691","documentation":"This is a Rust `.expect()` panic, not a catchable error. It fires when a managed file is marked `ManagedState::Present` while building the privileged `WriteFile` action, but its `content` field is `None`. The codebase's invariant is that any file declared Present must carry the content to write; a None here means the file was constructed incoherently.","triggerScenarios":"Calling the managed-file apply/plan path (src/system/managed_files.rs:673) with a `ManagedFile` whose `state` is `Present` but whose `content` was never set (constructed programmatically or deserialized from a config/partial state that omitted `content`).","commonSituations":"Hand-constructing a ManagedFile in a plugin or test; a config schema change that drops the `content` field; deserializing state from an older/other tool version that allowed Present without content.","solutions":["Set the `content` field whenever `state` is `ManagedState::Present` before invoking the apply path","Validate the file entry at construction/deserialization time and reject Present-without-content early with a real error","Switch the state to `ManagedState::Absent` if the file should only be removed, not written"],"exampleFix":"// before\nManagedFile { path, state: ManagedState::Present, content: None, .. }\n// after\nManagedFile { path, state: ManagedState::Present, content: Some(expected_content), .. }","handlingStrategy":"validation","validationCode":"fn validate_managed_file(f: &ManagedFile) -> Result<()> {\n    if f.state == ManagedState::Present && f.content.is_none() {\n        return Err(anyhow!(\"file {} marked Present but has no content\", f.path.display()));\n    }\n    Ok(())\n}","typeGuard":"fn has_content(f: &ManagedFile) -> bool {\n    f.state != ManagedState::Present || f.content.is_some()\n}","tryCatchPattern":null,"preventionTips":["Always pair ManagedState::Present with Some(content) at construction","Validate managed-file entries right after config deserialization","Prefer Absent state when content is unknown"],"tags":["panic","invariant","managed-files","config"],"backgroundTag":"internal-invariant-violation","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"}