{"record":{"id":"ca7a6d553586132b","repo":"unicity-aos/aos-ce","slug":"another-runtime-migration-is-already-in-progress","errorCode":null,"errorMessage":"another runtime migration is already in progress","messagePattern":"another runtime migration is already in progress","errorType":"validation","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/unicity-aos-bootstrap/src/migration.rs","lineNumber":213,"sourceCode":"    false\n}\n\nimpl MigrationLock {\n    fn acquire(home: &AosHome) -> io::Result<Self> {\n        let path = home.root().join(\"migrations\").join(LOCK_FILE);\n        let file = OpenOptions::new()\n            .read(true)\n            .write(true)\n            .create(true)\n            .truncate(false)\n            .open(&path)?;\n        if !file.metadata()?.is_file() {\n            return invalid(\"runtime migration lock must be a regular file\");\n        }\n        set_private_permissions(&path, false)?;\n        file.try_lock_exclusive().map_err(|error| {\n            if error.kind() == io::ErrorKind::WouldBlock {\n                io::Error::new(\n                    io::ErrorKind::WouldBlock,\n                    \"another runtime migration is already in progress\",\n                )\n            } else {\n                error\n            }\n        })?;\n        Ok(Self { _file: file })\n    }\n}\n\npub(crate) fn migrate_runtime(home: &AosHome, source: &Path) -> io::Result<MigrationOutcome> {\n    let source = checked_root(source, \"legacy runtime home\")?;\n    let target = checked_target_path(&home.runtime_home())?;\n    let release_runtime_bin = home.release_runtime_bin_dir();\n    if source == target || source.starts_with(&target) || target.starts_with(&source) {\n        return invalid(\"legacy runtime home and product runtime home must not overlap\");\n    }","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/crates/unicity-aos-bootstrap/src/migration.rs#L195-L231","documentation":"During migration, the library creates/opens a runtime migration lock file and attempts `try_lock_exclusive()`. A `WouldBlock` result means another migration process already holds this exclusive lock, so the library raises `WouldBlock` with this message to prevent concurrent migrations from corrupting state.","triggerScenarios":"Two `migrate_runtime` invocations overlapping — e.g. running the bootstrap migration command twice concurrently, or an automated job retried while the first attempt is still in progress.","commonSituations":"CI pipelines with retry logic re-launching the migration while the original still runs; two operators performing the upgrade simultaneously; a previous migration process stuck without releasing the lock.","solutions":["Wait for the in-progress migration to finish, then re-run.","Find the other migration process (`ps aux | grep <bootstrap>`) and confirm whether it is alive; kill it if it is hung.","Remove the stale migration lock file only after confirming no migration process is running, then retry.","Add an outer guard in your automation (e.g. flock around the whole migration command) to prevent concurrent invocations."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if migration_lock_exists_and_is_locked() {\n    return Err(anyhow!(\"another migration is already in progress; waiting\"));\n}","typeGuard":null,"tryCatchPattern":"match err.downcast_ref::<io::Error>() {\n    Some(e) if e.kind() == io::ErrorKind::WouldBlock && e.to_string().contains(\"already in progress\") => backoff_and_retry(),\n    _ => return Err(err),\n}","preventionTips":["Serialize migrations with an outer lock or job scheduler.","Never run the migration command concurrently from multiple shells/CI jobs.","Retry with exponential backoff instead of immediate parallel attempts."],"tags":["locking","concurrency","migration","rust"],"backgroundTag":"resource-already-locked","analyzedSha":"f6f22024fb1e8d122f28a1b4a9f75aee448ae839","analyzedAt":"2026-09-13T03:04:44.565Z","contentChangedAt":"2026-09-13T03:04:44.565Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}