paperclipai/paperclip · error · Error
Worktree seed lock ${lockPath} belongs to exited process ${c
Error message
Worktree seed lock ${lockPath} belongs to exited process ${currentOwner.pid}. Verify that no seed is running, then remove the stale lock and retry. What it means
Thrown by acquireWorktreeSeedLock when the lock file exists, parses to a valid owner, but the owning process pid is no longer alive (and not EPERM). This means a previous seed process died holding the lock; the guard refuses to silently steal it and asks the user to confirm no seed is running before removing it.
Source
Thrown at cli/src/commands/worktree.ts:1534
const current = await fsPromises.readFile(lockPath, "utf8").catch(() => null);
if (current && parseWorktreeSeedLockOwner(current)?.token === owner.token) {
await fsPromises.rm(lockPath, { force: true });
}
};
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "EEXIST") throw error;
}
const [rawOwner, lockStat] = await Promise.all([
fsPromises.readFile(lockPath, "utf8").catch(() => null),
fsPromises.stat(lockPath).catch(() => null),
]);
const currentOwner = rawOwner ? parseWorktreeSeedLockOwner(rawOwner) : null;
const malformedLockIsStale = Boolean(
lockStat && Date.now() - lockStat.mtimeMs >= WORKTREE_SEED_LOCK_MALFORMED_STALE_MS,
);
if (currentOwner && !processIsAlive(currentOwner.pid)) {
throw new Error(
`Worktree seed lock ${lockPath} belongs to exited process ${currentOwner.pid}. `
+ "Verify that no seed is running, then remove the stale lock and retry.",
);
}
if (!currentOwner && malformedLockIsStale) {
throw new Error(
`Worktree seed lock ${lockPath} is stale or malformed. `
+ "Verify that no seed is running, then remove the stale lock and retry.",
);
}
await new Promise((resolve) => setTimeout(resolve, WORKTREE_SEED_LOCK_POLL_MS));
}
}
export async function ensureWorktreeSeeded(
opts: WorktreeEnsureSeededOptions = {},
dependencies: { seedDatabase?: SeedWorktreeDatabase } = {},
): Promise<EnsureWorktreeSeededResult> {View on GitHub (pinned to 67001ec6eb)
Solutions
- Confirm no seed process is running (ps aux | grep paperclip).
- Remove the stale lock file at the path shown in the message.
- Retry the seed command.
- Investigate why the prior process died (OOM, disk full) to avoid recurrence.
Example fix
# before: stale lock from dead pid # after ps aux | grep paperclip # confirm none running rm <lockPath-from-error> paperclipai worktree reseed ...
Defensive patterns
Strategy: validation
Validate before calling
function lockOwnerIsAlive(lockPath: string): boolean {
const raw = fs.readFileSync(lockPath, 'utf8');
const owner = parseWorktreeSeedLockOwner(raw);
return owner ? processIsAlive(owner.pid) : false;
} Try / catch
try {
await acquireWorktreeSeedLock(lockPath);
} catch (e) {
if (/belongs to exited process/.test((e as Error).message)) {
if (!anySeedRunning()) fs.rmSync(lockPath, { force: true });
// retry
} else throw e;
} Prevention
- Always let seed processes exit cleanly.
- Check ps before removing stale locks.
- Wrap seeds in a process supervisor that releases locks.
When it happens
Trigger: A prior `paperclipai worktree reseed`/seed process was killed (SIGKILL, OOM, terminal closed) mid-seed; the lock file remained; a new seed attempt detects the dead owner.
Common situations: Long seed killed by timeout/OOM; user Ctrl-C'd then immediately retried before the lock was released; process died on a different host sharing the filesystem; IDE/shell closed abruptly.
Related errors
- Worktree seed lock ${lockPath} is stale or malformed. Verify
- Another restart for instance ${instanceId} is still running.
- Invalid worktree seed-pending marker at ${filePath}: ${error
- Invalid worktree seed-pending marker at ${filePath}.
- Source and target Paperclip configs are the same. Pass --fro
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/c8d5a3bd7fa57a1a.
Report an issue: GitHub.