{"record":{"id":"1ba694494f71f392","repo":"paperclipai/paperclip","slug":"workspace-repair-precondition-failed","errorCode":"workspace_repair_precondition_failed","errorMessage":"Workspace repair requires a registered base project workspace.","messagePattern":"Workspace repair requires a registered base project workspace\\.","errorType":"http","errorClass":"HttpError","httpStatus":422,"severity":"error","filePath":"server/src/routes/execution-workspaces.ts","lineNumber":402,"sourceCode":"      const manifestPath = path.join(workspaceCwd, \".paperclip\", \"seed-manifest.json\");\n      let manifest: {\n        attemptId?: unknown;\n        source?: { configPath?: unknown; instanceId?: unknown };\n        targetInstanceId?: unknown;\n      };\n      try {\n        manifest = JSON.parse(readFileSync(manifestPath, \"utf8\"));\n      } catch {\n        throw unprocessable(\"Workspace seed manifest is malformed; repair source identity cannot be trusted.\", {\n          code: \"workspace_repair_precondition_failed\",\n          reason: \"seed_manifest_malformed\",\n          repairPhase: \"precondition_validation\",\n        });\n      }\n\n      try {\n        if (!projectWorkspace?.cwd) {\n          throw new Error(\"Workspace repair requires a registered base project workspace.\");\n        }\n        const expectedTargetInstanceId = resolveManagedWorkspaceInstanceId(workspaceCwd);\n        if (!expectedTargetInstanceId) {\n          throw new Error(\"Workspace repair cannot resolve the registered target instance.\");\n        }\n        repairSeedSource = resolveCanonicalWorktreeSeedSource({\n          registeredBaseWorkspaceCwd: projectWorkspace.cwd,\n          explicitSourceConfigPath: resolveFallbackSeedSourceConfigPath(projectWorkspace.cwd),\n          targetConfigPath: path.join(workspaceCwd, \".paperclip\", \"config.json\"),\n          expectedTargetInstanceId,\n          manifestSource: manifest.source,\n          manifestTargetInstanceId: manifest.targetInstanceId,\n        });\n        repairPreviousAttemptId = typeof manifest.attemptId === \"string\" ? manifest.attemptId : null;\n\n        const baseWorkspaceCwd = repairSeedSource.baseWorkspaceCwd;\n        if (!baseWorkspaceCwd) {\n          throw new Error(\"Workspace repair source is not bound to a registered base project workspace.\");","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/paperclipai/paperclip/blob/a7e689b3c35347b529cb9f54c9b9a8575a3dcab6/server/src/routes/execution-workspaces.ts#L384-L420","documentation":"Thrown by the execution-workspace repair action (POST /execution-workspaces/:id/repair) when the workspace being repaired has no registered base project workspace. The repair flow reseeds a managed worktree's .paperclip database from a seed source that must live inside a registered project workspace checkout, so a missing or cwd-less project workspace row makes repair impossible. It is rethrown as HTTP 422 with code workspace_repair_precondition_failed and reason source_registration_invalid. The projectWorkspace row is looked up from existing.projectWorkspaceId scoped to the same company and project, so a null result means either no projectWorkspaceId was set or the referenced row no longer matches that scope.","triggerScenarios":"Calling the runtime command route with action=\"repair\" on an execution workspace whose projectWorkspaceId is null, or whose project_workspaces row was deleted or has a null/empty cwd (the DB select at server/src/routes/execution-workspaces.ts:291-310 returns null or a row without cwd). Always fires before any operation row or service mutation.","commonSituations":"Execution workspace created from a project that never registered a local base checkout; the base project workspace was deleted or re-registered after the execution workspace was seeded; a worktree whose parent project workspace record lost its cwd after a move of the repo on disk; company/project scoping mismatch after data imports.","solutions":["Check the execution workspace record: GET /api/execution-workspaces/:id and confirm projectWorkspaceId is set and non-null.","Verify the project workspace row exists and has a cwd: query project_workspaces by that id within the same company/project scope and confirm cwd is a non-empty, existing directory.","Re-register or fix the base project workspace (re-add the checkout so its cwd resolves), then retry the repair action.","If the base checkout genuinely no longer exists, re-create the execution workspace from a healthy base instead of repairing it."],"exampleFix":"// before\nawait api.post(`/api/execution-workspaces/${id}/repair`); // 422 workspace_repair_precondition_failed\n\n// after\nconst ws = await api.getExecutionWorkspace(id);\nif (!ws.projectWorkspaceId) throw new Error(\"Register a base project workspace before repair.\");\nconst base = await api.getProjectWorkspace(ws.projectWorkspaceId);\nif (!base?.cwd) throw new Error(\"Base project workspace has no cwd; re-register it.\");\nawait api.post(`/api/execution-workspaces/${id}/repair`);","handlingStrategy":"validation","validationCode":"const ws = await api.getExecutionWorkspace(id);\nif (!ws.projectWorkspaceId) throw new Error(\"Execution workspace has no base project workspace; register one before repair.\");\nconst base = await api.getProjectWorkspace(ws.projectWorkspaceId);\nif (!base?.cwd || !existsSync(base.cwd)) throw new Error(`Base project workspace cwd missing or absent: ${base?.cwd}`);","typeGuard":"function isRepairReadyWorkspace(ws: { projectWorkspaceId: string | null }, base: { cwd: string | null } | null): boolean {\n  return Boolean(ws.projectWorkspaceId && base?.cwd);\n}","tryCatchPattern":"try {\n  await api.post(`/api/execution-workspaces/${id}/repair`);\n} catch (err) {\n  if (err?.status === 422 && err.body?.details?.code === \"workspace_repair_precondition_failed\" && err.body?.details?.reason === \"source_registration_invalid\") {\n    // re-register the base project workspace, then retry\n  } else throw err;\n}","preventionTips":["Always register the base project workspace (with a real cwd) before creating execution workspaces that may need repair.","Never delete or move a project workspace checkout while execution workspaces still reference it.","Monitor the 422 reason field (source_registration_invalid vs seed_manifest_malformed) to distinguish registration problems from manifest corruption."],"tags":["workspace","repair","precondition","http-422","paperclip"],"backgroundTag":"resource-not-registered","analyzedSha":"a7e689b3c35347b529cb9f54c9b9a8575a3dcab6","analyzedAt":"2026-08-21T17:58:32.592Z","contentChangedAt":"2026-08-21T17:58:32.592Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}