paperclipai/paperclip · error · Error
Worktree seed source diagnostics changed while waiting for t
Error message
Worktree seed source diagnostics changed while waiting for the seed lock.
What it means
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.
Source
Thrown at cli/src/commands/worktree.ts:2334
// Resolve all authority-bearing paths before creating the lock. The manifest is
// agent-writable diagnostic evidence and never selects the source. A stale source
// diagnostic is replaced under the lock from this server/operator registration.
let canonicalSource = registeredSeedSource;
mkdirSync(path.dirname(markers.lock), { recursive: true });
const releaseLock = await acquireWorktreeSeedLock(markers.lock);
try {
// These checks deliberately happen under the cross-process lock. A second
// service process waits for the first seed transaction, then observes the
// verified manifest instead of cloning the same database concurrently.
let manifest = readWorktreeSeedManifest(configPath);
if (manifest?.state === "verified") {
return { seeded: false, reason: "verified_manifest" };
}
if (!manifest && existsSync(markers.pending)) {
const currentLegacyPending = readLegacyWorktreeSeedPendingMarker(markers.pending);
if (currentLegacyPending.sourceConfigPath !== legacyPending?.sourceConfigPath) {
throw new Error("Worktree seed source diagnostics changed while waiting for the seed lock.");
}
markWorktreeSeedPending({
configPath,
sourceConfigPath: registeredSeedSource.configPath,
targetInstanceId: targetPaths.instanceId,
seedMode: "minimal",
diagnosticMessage: "Re-derived seed source diagnostics from the registered canonical source.",
});
manifest = readWorktreeSeedManifest(configPath);
}
if (!manifest) {
const legacyEvidence = await (
dependencies.inspectLegacyDatabase ?? inspectLegacyWorktreeDatabase
)(configPath);
if (legacyEvidence) {
markWorktreeSeedPending({
configPath,
sourceConfigPath: registeredSeedSource.configPath,View on GitHub (pinned to a7e689b3c3)
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
Defensive patterns
Strategy: retry
Try / catch
for (let attempt = 0; attempt < 2; attempt++) {
try {
return await ensureWorktreeSeeded(opts);
} catch (error) {
if (!String(error).includes('source diagnostics changed')) throw error;
await stopCompetingSeedActors();
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Failed to create a pending worktree seed manifest.
- Cannot seed target embedded PostgreSQL at ${dataDir} while i
- Invalid worktree seed manifest at ${manifestPath}: ${error i
- Invalid worktree seed manifest at ${manifestPath}.
- Worktree seed manifest does not exist at ${markers.manifest}
AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-21).
Data as JSON: /api/errors/1f695a1af42a5db1.
Report an issue: GitHub.