unicity-aos/aos-ce · error · io::Error
standalone runtime has no existing system lock; refusing an…
Error message
standalone runtime has no existing system lock; refusing an unlocked migration
What it means
`SourceRuntimeLock::acquire` opens `<source>/run/system.lock` before migrating a standalone runtime. If the symlink metadata lookup fails with `NotFound`, the library refuses to proceed: migrating a source runtime that has no system lock would not be guarded against an active runtime, so it raises `InvalidInput`. The lock must already exist to prove the source is a real standalone runtime.
Solutions
- Verify the source path is the standalone runtime root containing `run/system.lock` (e.g. `ls <source>/run/system.lock`) and correct the path.
- If the runtime should be running/initialized, start it once so the runtime creates `run/system.lock`, then retry the migration.
- If the lock was deleted, restore the runtime layout (or reinstall) rather than hand-creating an empty lock, since the file must be a real regular file matching metadata.
- Ensure you are migrating the right runtime kind — a non-standalone runtime may legitimately lack this lock and is not a valid migration source.
Example fix
// before
migrate_runtime(Path::new("/opt/wrong-runtime"), ...);
// after
let source = Path::new("/opt/unicity-runtime");
assert!(source.join("run/system.lock").exists(), "missing run/system.lock");
migrate_runtime(source, ...); Defensive patterns
Strategy: validation
Validate before calling
let lock = source.join("run/system.lock");
if !lock.symlink_metadata().map(|m| m.is_file()).unwrap_or(false) {
return Err(anyhow!("{} is not a standalone runtime (missing run/system.lock)", source.display()));
} Try / catch
match err.downcast_ref::<io::Error>() {
Some(e) if e.kind() == io::ErrorKind::InvalidInput && e.to_string().contains("no existing system lock") => /* point at correct runtime root */,
_ => return Err(err),
} Prevention
- Verify the runtime root contains `run/system.lock` before migration.
- Start the runtime once before migrating so the runtime layout is complete.
- Distinguish runtime kinds — only standalone runtimes with this lock are valid migration sources.
When it happens
Trigger: Calling the migration entry point (which internally calls `SourceRuntimeLock::acquire`) against a source path whose `run/system.lock` file does not exist — e.g. wrong source path, never-started runtime, or a runtime layout where `run/` is missing.
Common situations: Pointing the migration at a stale or half-deleted installation, migrating a containerized/systemd runtime that stores its lock elsewhere, or a typo in the source directory passed on the command line.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- failed to inspect imported distro locks
- standalone runtime is active; stop it before migration
- another runtime migration is already in progress
- failed to preserve imported activation state
- failed to validate ephemeral state exclusion
AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13).
Data as JSON: /api/errors/4d217a500904e647.
Report an issue: GitHub.
Appendix: source
Thrown at crates/unicity-aos-bootstrap/src/migration.rs:157
let value = String::deserialize(deserializer)?;
Self::parse(&value).map_err(D::Error::custom)
}
}
struct MigrationLock {
_file: File,
}
struct SourceRuntimeLock {
_file: File,
}
impl SourceRuntimeLock {
fn acquire(source: &Path) -> io::Result<Self> {
let path = source.join("run/system.lock");
let path_metadata = fs::symlink_metadata(&path).map_err(|error| {
if error.kind() == io::ErrorKind::NotFound {
io::Error::new(
io::ErrorKind::InvalidInput,
"standalone runtime has no existing system lock; refusing an unlocked migration",
)
} else {
error
}
})?;
if path_metadata.file_type().is_symlink() || !path_metadata.is_file() {
return invalid("standalone runtime system lock must be a real regular file");
}
let file = OpenOptions::new().read(true).write(true).open(&path)?;
let file_metadata = file.metadata()?;
if !file_metadata.is_file() || !same_file(&path_metadata, &file_metadata) {
return invalid("standalone runtime system lock changed while it was opened");
}
file.try_lock_exclusive().map_err(|error| {
if error.kind() == io::ErrorKind::WouldBlock {
io::Error::new(View on GitHub (pinned to f6f22024fb)