jdx/mise · error
invalid cleanup target {}
Error message
invalid cleanup target {} What it means
clean_apk_transients validates every cleanup target via reject_symlink_components: after stripping the rootfs prefix, each remaining path component must be a plain Normal component. Anything else (ParentDir, RootDir, Prefix — including paths that resolve through '..') is rejected as an invalid cleanup target, guarding against deleting outside the rootfs.
Source
Thrown at src/oci/packages.rs:557
let cache = rootfs.join("var/cache/apk");
let log = rootfs.join("var/log/apk.log");
reject_symlink_components(rootfs, &cache)?;
reject_symlink_components(rootfs, &log)?;
remove_dir_children(&cache)?;
remove_path(&log)
}
/// Reject a cleanup target when it or any path component below `rootfs` is a
/// symlink. OCI package layers are untrusted, so following one during cleanup
/// could remove files outside the layer root.
fn reject_symlink_components(rootfs: &Path, target: &Path) -> Result<()> {
let relative = target
.strip_prefix(rootfs)
.wrap_err_with(|| format!("cleanup target {} is outside rootfs", target.display()))?;
let mut current = rootfs.to_path_buf();
for component in relative.components() {
let std::path::Component::Normal(component) = component else {
bail!("invalid cleanup target {}", target.display());
};
current.push(component);
match fs::symlink_metadata(¤t) {
Ok(metadata) if metadata.file_type().is_symlink() => {
bail!(
"refusing cleanup through symlink component {}",
current.display()
);
}
Ok(_) => {}
Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(()),
Err(err) => {
return Err(err)
.wrap_err_with(|| format!("reading metadata for {}", current.display()));
}
}
}
Ok(())View on GitHub (pinned to afd2eddd3a)
Solutions
- Inspect the rootfs for unexpected '..'-containing or absolute transient paths left by apk
- Rebuild from a clean base image so apk's transient files are in expected locations
- If reproducible, report it — this usually indicates malformed path state, not user configuration
Example fix
null
Defensive patterns
Strategy: try-catch
Validate before calling
null
Try / catch
try {
buildOciImage(config);
} catch (e) {
if (String(e.message).includes("invalid cleanup target")) {
// rebuild from a clean base image; report if reproducible
} else throw e;
} Prevention
- Build from clean, standard base images
- Avoid images with exotic path layouts in the apk db/cache locations
- Report reproducible occurrences upstream
When it happens
Trigger: clean_apk_transients computes a transient path (e.g. apk cache/db temp files) that normalizes to non-Normal components — typically because the stripped target still contains '..' or is a filesystem prefix — and reject_symlink_components bails.
Common situations: Corrupted or unexpected apk database paths inside the rootfs; symlinked or overlapping mount points causing odd relative paths; internal state bugs rather than user configuration errors.
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
- refusing cleanup through symlink component {}
- [dotfiles]."{}": target is not a safe OCI path
- mise oci needs a Linux host to install apk system packages i
- mise oci needs `apk` on PATH to install apk system packages
- mise oci needs to run as root to install apk system packages
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/3897b7825fd6c5ce.
Report an issue: GitHub.