{"record":{"id":"a3b31f0310923c0d","repo":"paperclipai/paperclip","slug":"worktree-seed-lock-lockpath-is-stale-or-malform","errorCode":null,"errorMessage":"Worktree seed lock ${lockPath} is stale or malformed. Verify that no seed is running, then remove the stale lock and retry.","messagePattern":"Worktree seed lock (.+?) is stale or malformed\\. Verify that no seed is running, then remove the stale lock and retry\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/commands/worktree.ts","lineNumber":1540,"sourceCode":"      if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n    }\n\n    const [rawOwner, lockStat] = await Promise.all([\n      fsPromises.readFile(lockPath, \"utf8\").catch(() => null),\n      fsPromises.stat(lockPath).catch(() => null),\n    ]);\n    const currentOwner = rawOwner ? parseWorktreeSeedLockOwner(rawOwner) : null;\n    const malformedLockIsStale = Boolean(\n      lockStat && Date.now() - lockStat.mtimeMs >= WORKTREE_SEED_LOCK_MALFORMED_STALE_MS,\n    );\n    if (currentOwner && !processIsAlive(currentOwner.pid)) {\n      throw new Error(\n        `Worktree seed lock ${lockPath} belongs to exited process ${currentOwner.pid}. `\n        + \"Verify that no seed is running, then remove the stale lock and retry.\",\n      );\n    }\n    if (!currentOwner && malformedLockIsStale) {\n      throw new Error(\n        `Worktree seed lock ${lockPath} is stale or malformed. `\n        + \"Verify that no seed is running, then remove the stale lock and retry.\",\n      );\n    }\n    await new Promise((resolve) => setTimeout(resolve, WORKTREE_SEED_LOCK_POLL_MS));\n  }\n}\n\nexport async function ensureWorktreeSeeded(\n  opts: WorktreeEnsureSeededOptions = {},\n  dependencies: { seedDatabase?: SeedWorktreeDatabase } = {},\n): Promise<EnsureWorktreeSeededResult> {\n  const configPath = resolveConfigPath(opts.config);\n  const markers = resolveWorktreeSeedMarkerPaths(configPath);\n  mkdirSync(path.dirname(markers.lock), { recursive: true });\n  const releaseLock = await acquireWorktreeSeedLock(markers.lock);\n  try {\n    // These checks deliberately happen under the cross-process lock. A second","sourceCodeStart":1522,"sourceCodeEnd":1558,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/commands/worktree.ts#L1522-L1558","documentation":"Thrown by acquireWorktreeSeedLock when the lock file exists but its content cannot be parsed into a valid owner AND the file's mtime is older than WORKTREE_SEED_LOCK_MALFORMED_STALE_MS (60s). This treats a corrupt/unrecognizable lock as stale only after the grace window, to avoid racing a live process that just hasn't finished writing.","triggerScenarios":"Lock file exists but is empty, partially written, or contains non-JSON/invalid JSON; more than 60 seconds have passed since its mtime; no current owner could be extracted to check liveness.","commonSituations":"Crash during lock write leaving a truncated file; another tool overwrote the lock with garbage; filesystem clock skew making mtime appear old; manual creation of an empty lock file.","solutions":["Confirm no seed is currently running.","Delete the malformed/stale lock file at the given path.","Retry the seed command.","If this recurs, check for processes or tools writing to the lock path, and filesystem sync/clock issues."],"exampleFix":"# before: malformed lock older than 60s\n# after\nps aux | grep paperclip\nrm <lockPath-from-error>\npaperclipai worktree reseed ...","handlingStrategy":"validation","validationCode":"function lockIsStaleOrMalformed(lockPath: string): boolean {\n  const raw = fs.readFileSync(lockPath, 'utf8').catch?.(() => null);\n  const owner = raw ? parseWorktreeSeedLockOwner(raw) : null;\n  const stat = fs.statSync(lockPath);\n  return !owner && Date.now() - stat.mtimeMs >= WORKTREE_SEED_LOCK_MALFORMED_STALE_MS;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await acquireWorktreeSeedLock(lockPath);\n} catch (e) {\n  if (/stale or malformed/.test((e as Error).message) && !anySeedRunning()) {\n    fs.rmSync(lockPath, { force: true }); // retry\n  } else throw e;\n}","preventionTips":["Confirm no seed is running before deleting locks.","Investigate recurring malformed locks (concurrent writers, clock skew).","Keep the seed lock write atomic."],"tags":["worktree","seed","lock","concurrency","stale","corruption"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}