Summary
After fixing #74346 (lock staleness check uses PID alone), there remains an edge case for legacy lock files created before the pidStartTimeMs and createdAtMs fields were added.
When a lock file has no starttime AND no createdAtMs, shouldRemoveRuntimeDepsLock() falls through to return false — the lock is considered fresh forever because pid is alive.
Reproduction
- Run OpenClaw in Docker with version before fix
2d885a2402 (2026.4.27 or earlier)
- Force-kill container (OOM,
docker kill, etc.) — leaves stale .openclaw-runtime-deps.lock/
- Start new container (PID 1, same namespace)
- New process reads legacy lock:
pid=1 alive=true, no starttime, no createdAtMs
shouldRemoveRuntimeDepsLock() returns false → 5-min timeout → crash loop
Evidence
Lock file from ~872 days ago:
ownerFile=ok (owner.json is valid)
pid=1 alive=true (current process)
ownerAge=72945443ms (legacy lock, no createdAtMs)
lockAge=72945443ms (lock dir untouched)
Fix
In shouldRemoveRuntimeDepsLock(), after checking starttime, add fallback staleness checks:
if (typeof owner.createdAtMs === "number" && owner.createdAtMs > 0) {
return nowMs - owner.createdAtMs > BUNDLED_RUNTIME_DEPS_LOCK_STALE_MS;
}
const legacyObservedAtMs = latestFiniteMs([
owner.lockDirMtimeMs,
owner.ownerFileMtimeMs,
]);
if (typeof legacyObservedAtMs === "number") {
return nowMs - legacyObservedAtMs > BUNDLED_RUNTIME_DEPS_LOCK_STALE_MS;
}
Fix committed
- Commit:
cfa8ae8d6c — fix(plugins): expire legacy runtime-deps locks in Docker when lock dir is stale
- Files:
src/plugins/bundled-runtime-deps-lock.ts, `src/plugins/bundled-runtime-deps.test.ts
Summary
After fixing #74346 (lock staleness check uses PID alone), there remains an edge case for legacy lock files created before the
pidStartTimeMsandcreatedAtMsfields were added.When a lock file has no
starttimeAND nocreatedAtMs,shouldRemoveRuntimeDepsLock()falls through toreturn false— the lock is considered fresh forever becausepidis alive.Reproduction
2d885a2402(2026.4.27 or earlier)docker kill, etc.) — leaves stale.openclaw-runtime-deps.lock/pid=1 alive=true, nostarttime, nocreatedAtMsshouldRemoveRuntimeDepsLock()returnsfalse→ 5-min timeout → crash loopEvidence
Lock file from ~872 days ago:
ownerFile=ok(owner.json is valid)pid=1 alive=true(current process)ownerAge=72945443ms(legacy lock, no createdAtMs)lockAge=72945443ms(lock dir untouched)Fix
In
shouldRemoveRuntimeDepsLock(), after checkingstarttime, add fallback staleness checks:Fix committed
cfa8ae8d6c—fix(plugins): expire legacy runtime-deps locks in Docker when lock dir is stalesrc/plugins/bundled-runtime-deps-lock.ts, `src/plugins/bundled-runtime-deps.test.ts