{"record":{"id":"c55fa5f4bd51da91","repo":"paperclipai/paperclip","slug":"failed-to-merge-concurrent-ssh-git-histories-for","errorCode":null,"errorMessage":"Failed to merge concurrent SSH git histories for ${currentHead.slice(0, 12)} and ${input.importedHead.slice(0, 12)}: ${reason}","messagePattern":"Failed to merge concurrent SSH git histories for (.+?) and (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/adapter-utils/src/ssh.ts","lineNumber":965,"sourceCode":"          timeout: 10_000,\n          maxBuffer: 16 * 1024,\n        });\n        return;\n      } catch (error) {\n        if (isConcurrentRefUpdateError(error) && attempt < 4) continue;\n        throw error;\n      }\n    }\n\n    let mergedTree;\n    try {\n      mergedTree = await runLocalGit(input.localDir, [\"merge-tree\", \"--write-tree\", currentHead, input.importedHead], {\n        timeout: 60_000,\n        maxBuffer: 256 * 1024,\n      });\n    } catch (error) {\n      const reason = error instanceof Error ? error.message : String(error);\n      throw new Error(\n        `Failed to merge concurrent SSH git histories for ${currentHead.slice(0, 12)} and ${input.importedHead.slice(0, 12)}: ${reason}`,\n      );\n    }\n    const mergedTreeId = mergedTree.stdout.trim().split(\"\\n\")[0]?.trim() ?? \"\";\n    if (!mergedTreeId) {\n      throw new Error(\"Failed to compute a merged git tree for SSH workspace restore.\");\n    }\n\n    const mergeCommit = await runLocalGit(\n      input.localDir,\n      [\n        \"commit-tree\",\n        mergedTreeId,\n        \"-p\",\n        currentHead,\n        \"-p\",\n        input.importedHead,\n        \"-m\",","sourceCodeStart":947,"sourceCodeEnd":983,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/adapter-utils/src/ssh.ts#L947-L983","documentation":"Thrown during SSH workspace restore when `git merge-tree --write-tree <currentHead> <importedHead>` fails. The local git repo has divergent histories (the remote SSH workspace and the imported snapshot both advanced) and git could not compute a merge tree — typically because of a real merge conflict or a corrupted object. The wrapped reason preserves git's own error text.","triggerScenarios":"mergeConcurrentSshGitHistories (ssh.ts) detects currentHead !== importedHead and neither is an ancestor of the other (true divergence), then runs git merge-tree --write-tree which exits non-zero. Triggers on conflicting edits to the same files in both the SSH workspace and the imported restore snapshot.","commonSituations":"Two agents editing the same workspace file from different lanes; a restore attempted against a workspace that moved forward with conflicting changes; large repo where merge-tree hit the 256KB maxBuffer or 60s timeout; corrupted .git objects from an interrupted sync.","solutions":["Inspect the wrapped `reason` in the message: a conflict-style output means real content conflicts that need manual resolution before re-running the restore.","If reason mentions timeout/buffer, raise the merge-tree budget or reduce workspace size; re-run restore when the workspace is quieter.","Run `git merge-tree --write-tree <currentHead> <importedHead>` manually in input.localDir to reproduce and resolve the conflict.","If the histories should not have diverged, verify the importedHead was captured from a consistent snapshot and retry after resetting the workspace to a known-good head."],"exampleFix":"// before: restore divergent SSH workspace\nawait restoreSshWorkspace({ localDir, importedHead, spec });\n// after: resolve the conflict locally first\n// cd <localDir> && git merge-tree --write-tree <currentHead> <importedHead>\n// fix conflicts, then re-run restore with a rebased importedHead","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await restoreSshWorkspace({ localDir, importedHead, spec });\n} catch (err) {\n  if (err.message.startsWith(\"Failed to merge concurrent SSH git histories\")) {\n    // log importedHead/currentHead, surface conflict for manual resolution,\n    // do not retry blindly — the underlying merge-tree conflict persists.\n  }\n  throw err;\n}","preventionTips":["Avoid concurrent edits to the same SSH workspace from multiple lanes.","Capture workspace snapshots at quiescent points to minimize divergence.","Inspect the wrapped git reason before retrying — content conflicts will not self-heal."],"tags":["git","ssh","workspace-restore","merge-conflict","paperclip"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}