unicity-aos/aos-ce · error · io::Error

standalone runtime is active; stop it before migration

Error message

standalone runtime is active; stop it before migration

What it means

`SourceRuntimeLock::acquire` opens `run/system.lock` and tries `try_lock_exclusive()`. If the OS returns `WouldBlock`, another process (the live standalone runtime) already holds the lock, so migration would race with a running runtime; the library raises `WouldBlock` with this message.

Solutions

  1. Stop the standalone runtime (e.g. `systemctl stop <unit>` or the equivalent service command) so it releases `run/system.lock`, then re-run the migration.
  2. Check for lingering processes holding the lock (`lsof <source>/run/system.lock` or `fuser`) and terminate them.
  3. If the runtime was killed but a child still holds the fd, wait or reboot the host before migrating.
  4. Serialize migrations through a job scheduler so only one migration runs at a time.
Defensive patterns

Strategy: try-catch

Validate before calling

let lock = source.join("run/system.lock");
if let Ok(f) = std::fs::File::open(&lock) {
    if f.try_lock_exclusive().is_err() {
        return Err(anyhow!("standalone runtime is active; stop it first"));
    }
}

Try / catch

match err.downcast_ref::<io::Error>() {
    Some(e) if e.kind() == io::ErrorKind::WouldBlock && e.to_string().contains("runtime is active") => stop_runtime_and_retry(),
    _ => return Err(err),
}

Prevention

When it happens

Trigger: Running the migration while the standalone runtime is still running and holding an exclusive lock on `run/system.lock`, or while a previous migration/service holds the file lock without having exited cleanly.

Common situations: Forgetting to stop the systemd unit or background daemon before migrating; another administrator or automation job migrating concurrently; a hung runtime process keeping the lock.

Related errors


AI-assisted analysis of unicity-aos/aos-ce@f6f22024fb (2026-09-13). Data as JSON: /api/errors/9056ab049c04ac16. Report an issue: GitHub.

Appendix: source

Thrown at crates/unicity-aos-bootstrap/src/migration.rs:175

                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(
                    io::ErrorKind::WouldBlock,
                    "standalone runtime is active; stop it before migration",
                )
            } else {
                error
            }
        })?;
        Ok(Self { _file: file })
    }
}

#[cfg(unix)]
fn same_file(left: &fs::Metadata, right: &fs::Metadata) -> bool {
    use std::os::unix::fs::MetadataExt;
    left.dev() == right.dev() && left.ino() == right.ino()
}

#[cfg(not(unix))]

View on GitHub (pinned to f6f22024fb)