astrid-runtime/astrid · error
legacy state source is an active mount: {}
Error message
legacy state source is an active mount: {} What it means
ensure_legacy_tree_boundary rejects a legacy tree root that is itself an active mountpoint (checked via is_active_mountpoint). Deleting a mounted directory would either fail or, worse, let the library descend through the mount; retirement therefore refuses with InvalidData.
Source
Thrown at crates/astrid-core/src/dirs_layout_retirement.rs:248
root_device: u64,
metadata: &std::fs::Metadata,
) -> io::Result<()> {
#[cfg(unix)]
{
if legacy_tree_device(metadata) != root_device {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"legacy state source crosses a filesystem boundary: {}",
path.display()
),
));
}
}
#[cfg(not(unix))]
let _ = (root_device, metadata);
if is_active_mountpoint(path)? {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("legacy state source is an active mount: {}", path.display()),
));
}
Ok(())
}
#[cfg(target_os = "linux")]
pub(super) fn is_active_mountpoint(path: &Path) -> io::Result<bool> {
let canonical = std::fs::canonicalize(path)?;
let mountinfo = std::fs::read_to_string("/proc/self/mountinfo")?;
Ok(mountinfo.lines().any(|line| {
let Some(mountpoint) = line.split_whitespace().nth(4) else {
return false;
};
decode_mountinfo_path(mountpoint).is_some_and(|mountpoint| mountpoint == canonical)
}))
}View on GitHub (pinned to affd8760f4)
Solutions
- Unmount the mountpoint: umount <path> (or stop the systemd mount unit / container holding it), then retry retirement.
- Move any data you need off the mounted volume first, since the legacy tree being retired should be empty or disposable.
- If a service keeps re-mounting it, disable the mount unit or stop the workload before retiring.
Example fix
// before mount | grep legacy -> /dev/sdb1 on /data/legacy // after umount /data/legacy
Defensive patterns
Strategy: validation
Validate before calling
fn assert_not_mountpoint(p: &Path) -> io::Result<()> {
let parent_dev = std::fs::metadata(p.parent().unwrap())?.dev(); // unix
let dev = std::fs::metadata(p)?.dev();
if dev != parent_dev {
return Err(io::Error::new(io::ErrorKind::InvalidData, "active mountpoint"));
}
Ok(())
} Type guard
fn is_mountpoint(p: &Path) -> bool {
match (std::fs::metadata(p), p.parent().and_then(|q| std::fs::metadata(q).ok())) {
(Ok(c), Some(par)) => c.dev() != par.dev(),
_ => false,
}
} Try / catch
match retire_legacy_source_tree(&path, dev) {
Err(e) if e.to_string().contains("active mount") => { /* umount + stop mount units, retry */ }
other => other?,
} Prevention
- Check /proc/mounts or `mountpoint <path>` before retirement
- Disable systemd automount units targeting state paths
- Ensure containers are stopped and volumes detached first
When it happens
Trigger: retire_legacy_source_tree is called while the legacy source path (or, combined with 1205, any entry) is an active mountpoint — e.g. a volume is mounted exactly at the legacy state dir.
Common situations: Container runtime still has a volume mounted at the data path; systemd automount/tmpfs unit active; admin mounted a new disk at the old state location before migration.
Related errors
- mountpoint is already registered: {}
- legacy state source crosses a filesystem boundary: {}
- legacy source is an active mount: {}
- legacy source crosses a device boundary: {}
- directory symlink {} not allowed in capsule source tree (ref
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/ce0566842a303cb0.
Report an issue: GitHub.