jdx/mise · error
invalid recovery destination
Error message
invalid recovery destination
What it means
validate_destination rejects a recovery destination that is not an absolute path or contains a `..` (ParentDir) component. This is a safety check so the restore step can never write outside the intended location or depend on relative-path resolution. It indicates corrupt or malicious journal data rather than anything the user did at runtime.
Source
Thrown at src/system/history/recovery.rs:111
after,
PathState::Dir {
identity: Some(_),
..
}
))
{
bail!("directory contents cannot be verified safely; left untouched");
}
validate_snapshot(state_dir, prior)?;
if PathState::observe(path) != *after {
bail!("changed while preparing recovery; left untouched");
}
restore(state_dir, path, prior)
}
fn validate_destination(path: &Path) -> Result<()> {
if !path.is_absolute() || path.components().any(|c| matches!(c, Component::ParentDir)) {
bail!("invalid recovery destination");
}
for parent in path.ancestors().skip(1) {
if std::fs::symlink_metadata(parent).is_ok_and(|meta| meta.is_symlink()) {
bail!("a parent directory is now a symlink; left untouched");
}
}
Ok(())
}
fn validate_blob_id(hash: &str) -> Result<()> {
if hash.len() != 64 || !hash.bytes().all(|b| b.is_ascii_hexdigit()) {
bail!("invalid recovery content identifier");
}
Ok(())
}
pub(super) fn read_blob(state_dir: &Path, blob: &Blob) -> Result<Vec<u8>> {
use base64::Engine;View on GitHub (pinned to afd2eddd3a)
Solutions
- Inspect the pending journal in the state directory for entries with relative or `..` paths and correct or remove them.
- Delete the corrupt pending-operation record (accepting current file contents) if its journal cannot be trusted.
- Report it as a bug if no one edited the state directory: journal entries should always carry canonical absolute paths.
Example fix
// before (corrupt journal entry) "path": "../home/user/.zshrc" // after (canonical absolute path) "path": "/home/user/.zshrc"
Defensive patterns
Strategy: validation
Validate before calling
// before trusting a journal, verify destinations
fn is_safe_destination(p: &std::path::Path) -> bool {
p.is_absolute() && !p.components().any(|c| matches!(c, std::path::Component::ParentDir))
} Try / catch
match result { Err(e) if e.to_string().contains("invalid recovery destination") => /* journal corrupt; discard record and restore manually */, other => other? } Prevention
- Never hand-edit pending-operation journal files
- Restrict write access to the mise state directory (permissions 0700)
- Canonicalize paths to absolute form before recording operations
When it happens
Trigger: recover_path -> validate_destination receives a journal entry whose PathChanged path is relative or contains `..` components; typically only possible with a hand-edited or corrupted pending-operation journal in the state directory.
Common situations: A corrupted state directory, a journal file modified by hand or by an untrusted tool, or a bug in code that constructed journal entries with non-canonicalized paths.
Understand the failure class
Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.
Related errors
- invalid path inside recovery directory
- [dotfiles]."{}": target is not a safe OCI path
- brew-cask: invalid {kind} '{value}'
- brew-cask: staged symlink path escaped extraction root: {}
- brew-cask: refusing generic artifact source outside the extr
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/08573704413e1db9.
Report an issue: GitHub.