paperclipai/paperclip · error · WorkspaceValidationFailure

git_worktree_provider_ref_mismatch

git_worktree_provider_ref_mismatch

Error message

Issue ${issue.identifier ?? issue.id} expected git worktree "${input.persistedExecutionWorkspace.providerRef}" but adapter cwd resolved to "${effectiveCwd}".

What it means

A git-worktree-based execution workspace was expected (providerRef names the registered worktree), but the adapter's resolved cwd points somewhere else. This mismatch guard fires during heartbeat pre-flight to prevent runs that would execute outside the persisted worktree.

Solutions

  1. Restore or recreate the git worktree so the adapter cwd matches the persisted provider ref.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/src/services/heartbeat.ts:2134 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-08-18). Data as JSON: /api/errors/5a98f5b05018a268. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/heartbeat.ts:2549

    // Preserve the closed failure code without copying subprocess output or
    // credentials into the durable run. Setup recovery needs the actual cause.
    if (isWorkspaceGitScanError(error)) throw new WorkspaceGitScanError(error.code, message);
    throw new Error(message);
  }

  try {
    await fs.rename(cloneTmpDir, cwd);
  } catch (renameError) {
    await fs
      .rm(cloneTmpDir, { recursive: true, force: true })
      .catch(() => undefined);
    // The target appearing between the emptiness check and the rename means another
    // materialization won the race; adopt its checkout instead of failing the run.
    if (await hasAdoptableGitDir()) {
      return { cwd, warning: null };
    }
    const reason =
      renameError instanceof Error ? renameError.message : String(renameError);
    throw new Error(
      `Failed to move managed checkout into place at "${cwd}": ${reason}`,
    );
  }
  return { cwd, warning: null };
}

/** Keep every distinct project repository inside the task's writable/synced root. */
export async function prepareProjectRepositoryWorkspaces(input: {
  cwd: string;
  anchorRepoUrl: string | null;
  workspaces: Array<Pick<typeof projectWorkspaces.$inferSelect, "id" | "repoUrl" | "repoRef"> & { cwd?: string | null }>;
  resolveGitAuth?: GitRemoteAuthProvider | null;
}): Promise<Array<{ workspaceId: string; cwd: string; repoUrl: string; repoRef: string | null }>> {
  const identity = (url: string) => url.trim().replace(/\.git\/?$/, "").replace(/\/$/, "");
  const seen = new Set(input.anchorRepoUrl ? [identity(input.anchorRepoUrl)] : []);
  const selected = input.workspaces.filter((workspace) => {
    if (!workspace.repoUrl || seen.has(identity(workspace.repoUrl))) return false;

View on GitHub (pinned to 3f1d897a7c)