{"record":{"id":"0bc99bdb2c42a789","repo":"paperclipai/paperclip","slug":"persisted-cwd-mismatch","errorCode":"persisted_cwd_mismatch","errorMessage":"Issue ${issue.identifier ?? issue.id} resolved adapter cwd \"${effectiveCwd}\" but persisted execution workspace cwd is \"${persistedCwd}\".","messagePattern":"Issue (.+?) resolved adapter cwd \"(.+?)\" but persisted execution workspace cwd is \"(.+?)\"\\.","errorType":"validation","errorClass":"WorkspaceValidationFailure","httpStatus":null,"severity":"error","filePath":"server/src/services/heartbeat.ts","lineNumber":2549,"sourceCode":"    // Preserve the closed failure code without copying subprocess output or\n    // credentials into the durable run. Setup recovery needs the actual cause.\n    if (isWorkspaceGitScanError(error)) throw new WorkspaceGitScanError(error.code, message);\n    throw new Error(message);\n  }\n\n  try {\n    await fs.rename(cloneTmpDir, cwd);\n  } catch (renameError) {\n    await fs\n      .rm(cloneTmpDir, { recursive: true, force: true })\n      .catch(() => undefined);\n    // The target appearing between the emptiness check and the rename means another\n    // materialization won the race; adopt its checkout instead of failing the run.\n    if (await hasAdoptableGitDir()) {\n      return { cwd, warning: null };\n    }\n    const reason =\n      renameError instanceof Error ? renameError.message : String(renameError);\n    throw new Error(\n      `Failed to move managed checkout into place at \"${cwd}\": ${reason}`,\n    );\n  }\n  return { cwd, warning: null };\n}\n\n/** Keep every distinct project repository inside the task's writable/synced root. */\nexport async function prepareProjectRepositoryWorkspaces(input: {\n  cwd: string;\n  anchorRepoUrl: string | null;\n  workspaces: Array<Pick<typeof projectWorkspaces.$inferSelect, \"id\" | \"repoUrl\" | \"repoRef\"> & { cwd?: string | null }>;\n  resolveGitAuth?: GitRemoteAuthProvider | null;\n}): Promise<Array<{ workspaceId: string; cwd: string; repoUrl: string; repoRef: string | null }>> {\n  const identity = (url: string) => url.trim().replace(/\\.git\\/?$/, \"\").replace(/\\/$/, \"\");\n  const seen = new Set(input.anchorRepoUrl ? [identity(input.anchorRepoUrl)] : []);\n  const selected = input.workspaces.filter((workspace) => {\n    if (!workspace.repoUrl || seen.has(identity(workspace.repoUrl))) return false;","sourceCodeStart":2531,"sourceCodeEnd":2567,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/heartbeat.ts#L2531-L2567","documentation":"The heartbeat pre-flight check found the adapter resolved a different working directory than the cwd persisted on the execution workspace record. It fires when executionWorkspace.cwd and persistedExecutionWorkspace.cwd disagree, meaning the run would operate on an untracked directory; the mismatch must be reconciled before launch.","triggerScenarios":"Thrown at server/src/services/heartbeat.ts:2134 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Re-resolve the execution workspace so the persisted cwd matches the adapter cwd, or recreate the execution workspace."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}