{"record":{"id":"3a3f2eb8383a49ca","repo":"paperclipai/paperclip","slug":"workspace-database-repair-command-timed-out-during","errorCode":null,"errorMessage":"Workspace database repair command timed out during ${repairPhase}.","messagePattern":"Workspace database repair command timed out during (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/routes/execution-workspaces.ts","lineNumber":775,"sourceCode":"              let seedFailurePhase: string | null = null;\n              try {\n                const failedManifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as {\n                  phase?: unknown;\n                  state?: unknown;\n                };\n                seedFailurePhase = failedManifest.state === \"failed\" && typeof failedManifest.phase === \"string\"\n                  ? failedManifest.phase\n                  : null;\n              } catch {\n                // The outer repair phase remains exact when no seed phase was persisted.\n              }\n              await reportProgress({\n                metadata: { seedFailurePhase },\n                system: seedFailurePhase ? `Workspace seed failed during ${seedFailurePhase}.\\n` : null,\n              });\n              throw new Error(\n                repairCommandTimedOut\n                  ? `Workspace database repair command timed out during ${repairPhase}.`\n                  : `Workspace database repair command failed during ${repairPhase}.`,\n              );\n            }\n            if (!reseedObserved) {\n              await reportRepairPhase(\"target_backup\", \"succeeded\");\n              await reportRepairPhase(\"full_reseed\", \"started\");\n            }\n\n            const manifest = JSON.parse(readFileSync(manifestPath, \"utf8\")) as Record<string, unknown>;\n            if (!isVerifiedWorktreeSeedManifest(manifest)) {\n              throw new Error(\"Workspace reseed returned without a verified terminal manifest.\");\n            }\n            const expectedInstanceId = resolveManagedWorkspaceInstanceId(workspaceCwd);\n            if (manifest.targetInstanceId !== expectedInstanceId) {\n              throw repairPreconditionError(\n                422,\n                \"seed_manifest_instance_mismatch\",\n                \"Verified seed manifest belongs to a different workspace instance.\",","sourceCodeStart":757,"sourceCodeEnd":793,"githubUrl":"https://github.com/paperclipai/paperclip/blob/a7e689b3c35347b529cb9f54c9b9a8575a3dcab6/server/src/routes/execution-workspaces.ts#L757-L793","documentation":"Thrown when the repair reseed child process exceeds the hard 20-minute budget. The route spawns node <cli> worktree reseed ... and arms a timer (server/src/routes/execution-workspaces.ts:715-720) that SIGTERMs the child at 20 minutes and SIGKILLs 5 seconds later; a non-zero exit with repairCommandTimedOut=true produces this message, naming the outer repair phase (target_backup or full_reseed) the flow had reached. The worktree itself is preserved (worktreePreserved, databaseOnly) and the failed phase is reported on the workspace operation.","triggerScenarios":"POST repair where the full reseed of the worktree database takes longer than 20 minutes: very large base database, slow disk/network-attached storage, lock contention on the base .paperclip database, or the child hanging on a prompt because --yes did not cover an interactive path. The interval poll (manifestPoll) determines whether the phase is reported as full_reseed vs target_backup.","commonSituations":"Base workspace with a multi-GB PGlite/pg data directory copied over NFS; a seeded company with huge issue/comment history; concurrent repairs or an active seed against the same base starving I/O; a CLI version that stalls waiting for a lock on the source database.","solutions":["Check the workspace operation record and captured child stdout/stderr to see how far the reseed got before the kill.","Eliminate I/O contention: stop concurrent repairs/seeds against the same base, repair from faster local disk.","Shrink the seed scope if the CLI supports it (seed mode filters), or prune/archieve old data in the base workspace database.","Retry the repair — the target is backed up first (--backup-target) so a timed-out attempt is safe to re-run.","If large databases are the norm, raise the fixed 20-minute budget in server/src/routes/execution-workspaces.ts:715 as a code change."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Estimate before repair: check base .paperclip database size on disk\nconst sizeBytes = await du(path.join(baseCwd, \".paperclip\"));\nif (sizeBytes > LARGE_SEED_THRESHOLD) { /* schedule during low load, or prune base data first */ }","typeGuard":null,"tryCatchPattern":"try {\n  await repair(id);\n} catch (err) {\n  if (/timed out during/.test(String(err?.body?.error ?? err?.message ?? \"\"))) {\n    // reseed target is backed up and worktree preserved — safe to retry after reducing I/O load\n    await waitForIdleIo(); await repair(id);\n  } else throw err;\n}","preventionTips":["Keep base workspace databases pruned so full reseeds stay well under the 20-minute budget.","Do not run multiple repairs/seeds against the same base concurrently.","Keep the worktree and base on fast local disk, not network storage."],"tags":["workspace","repair","timeout","child-process","reseed","paperclip"],"backgroundTag":"child-process-timeout","analyzedSha":"a7e689b3c35347b529cb9f54c9b9a8575a3dcab6","analyzedAt":"2026-08-21T17:58:32.592Z","contentChangedAt":"2026-08-21T17:58:32.592Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}