{"record":{"id":"1f695a1af42a5db1","repo":"paperclipai/paperclip","slug":"worktree-seed-source-diagnostics-changed-while-wai","errorCode":null,"errorMessage":"Worktree seed source diagnostics changed while waiting for the seed lock.","messagePattern":"Worktree seed source diagnostics changed while waiting for the seed lock\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/commands/worktree.ts","lineNumber":2334,"sourceCode":"\n  // Resolve all authority-bearing paths before creating the lock. The manifest is\n  // agent-writable diagnostic evidence and never selects the source. A stale source\n  // diagnostic is replaced under the lock from this server/operator registration.\n  let canonicalSource = registeredSeedSource;\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\n    // service process waits for the first seed transaction, then observes the\n    // verified manifest instead of cloning the same database concurrently.\n    let manifest = readWorktreeSeedManifest(configPath);\n    if (manifest?.state === \"verified\") {\n      return { seeded: false, reason: \"verified_manifest\" };\n    }\n    if (!manifest && existsSync(markers.pending)) {\n      const currentLegacyPending = readLegacyWorktreeSeedPendingMarker(markers.pending);\n      if (currentLegacyPending.sourceConfigPath !== legacyPending?.sourceConfigPath) {\n        throw new Error(\"Worktree seed source diagnostics changed while waiting for the seed lock.\");\n      }\n      markWorktreeSeedPending({\n        configPath,\n        sourceConfigPath: registeredSeedSource.configPath,\n        targetInstanceId: targetPaths.instanceId,\n        seedMode: \"minimal\",\n        diagnosticMessage: \"Re-derived seed source diagnostics from the registered canonical source.\",\n      });\n      manifest = readWorktreeSeedManifest(configPath);\n    }\n    if (!manifest) {\n      const legacyEvidence = await (\n        dependencies.inspectLegacyDatabase ?? inspectLegacyWorktreeDatabase\n      )(configPath);\n      if (legacyEvidence) {\n        markWorktreeSeedPending({\n          configPath,\n          sourceConfigPath: registeredSeedSource.configPath,","sourceCodeStart":2316,"sourceCodeEnd":2352,"githubUrl":"https://github.com/paperclipai/paperclip/blob/a7e689b3c35347b529cb9f54c9b9a8575a3dcab6/cli/src/commands/worktree.ts#L2316-L2352","documentation":"ensureWorktreeSeeded reads the legacy pending marker before acquiring the seed lock; under the lock it re-reads it and verifies the sourceConfigPath is unchanged. The lock is a polled cross-process lock (WORKTREE_SEED_LOCK_POLL_MS = 50), and this check detects that another actor rewrote the legacy source diagnostics while this process waited — i.e. two seed processes with different sources are racing on one worktree.","triggerScenarios":"Two concurrent seed invocations with different registered/explicit sources for the same worktree: the first holds the lock and mutates legacy diagnostics; the second acquires the lock afterward and sees a different sourceConfigPath than its pre-lock read.","commonSituations":"Two services or terminals seeding the same worktree from different sources; a re-registration pointing at a new source while an old seed was still queued; automation overlapping ensure-seeded runs.","solutions":["Ensure a single seed source per worktree: stop the competing service/process, then retry the seed","If the legacy pending marker is definitively stale (no other seed running), remove it and re-run ensureWorktreeSeeded","Re-register the worktree with one canonical source before seeding again"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"for (let attempt = 0; attempt < 2; attempt++) {\n  try {\n    return await ensureWorktreeSeeded(opts);\n  } catch (error) {\n    if (!String(error).includes('source diagnostics changed')) throw error;\n    await stopCompetingSeedActors();\n  }\n}","preventionTips":["Ensure exactly one seed source and one seed process per worktree","Serialize ensure-seeded invocations behind your own lock if multiple services share a worktree"],"tags":["worktree","seed","concurrency","locking","manifest"],"backgroundTag":"concurrent-seed-conflict","analyzedSha":"a7e689b3c35347b529cb9f54c9b9a8575a3dcab6","analyzedAt":"2026-08-21T17:58:32.592Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}