{"record":{"id":"1b49d5e841d0561c","repo":"paperclipai/paperclip","slug":"failed-to-integrate-concurrent-remote-git-history","errorCode":null,"errorMessage":"Failed to integrate concurrent remote git history for ${input.importedHead.slice(0, 12)} after multiple retries.","messagePattern":"Failed to integrate concurrent remote git history for (.+?) after multiple retries\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/adapter-utils/src/git-workspace-sync.ts","lineNumber":464,"sourceCode":"      ],\n      {\n        timeout: 60_000,\n        maxBuffer: 64 * 1024,\n      },\n    );\n    try {\n      await runLocalGit(input.localDir, [\"update-ref\", headRef, mergeCommit.stdout.trim(), currentHead], {\n        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  throw new Error(`Failed to integrate concurrent remote git history for ${input.importedHead.slice(0, 12)} after multiple retries.`);\n}\n\nexport async function resetLocalGitIndexToHead(input: {\n  localDir: string;\n  checkWorkingTreeClean?: boolean;\n}): Promise<void> {\n  try {\n    await runLocalGit(input.localDir, [\"reset\", \"--quiet\", \"HEAD\", \"--\", \".\"], {\n      timeout: 60_000,\n      maxBuffer: 1024 * 1024,\n    });\n  } catch (error) {\n    const detail = error && typeof error === \"object\"\n      ? [\n        (error as { message?: unknown }).message,\n        (error as { stderr?: unknown }).stderr,\n        (error as { stdout?: unknown }).stdout,\n      ].filter((value): value is string => typeof value === \"string\" && value.trim().length > 0).join(\"\\n\")","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/adapter-utils/src/git-workspace-sync.ts#L446-L482","documentation":"Thrown by integrateImportedGitHead after all 5 retry attempts fail with concurrent ref update lock errors. Each attempt calls `git update-ref` which fails with 'cannot lock ref ... expected ...', indicating another process is concurrently updating the same git ref. After exhausting retries, the integration gives up.","triggerScenarios":"Calling integrateImportedGitHead in a context where another concurrent process (another agent run, a parallel workspace sync, or a git gc) is locking the same ref. All 5 iterations of the for-loop hit isConcurrentRefUpdateError(error) and attempt < 4 continues, then the loop exits and this terminal throw fires.","commonSituations":"Multiple agent runs syncing to the same workspace simultaneously; a long-running git gc or repack holding ref locks; stale .git/refs/<ref>.lock files left by a crashed process; NFS or shared-filesystem lock contention.","solutions":["Serialize workspace sync operations so only one integrateImportedGitHead runs at a time per workspace.","Remove stale git lock files (`.git/*.lock`, `.git/refs/**/*.lock`) if a previous process crashed.","Check for concurrent agent runs targeting the same localDir and coordinate them.","If on NFS/shared storage, move the workspace to a local filesystem to reduce lock contention."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Check for stale lock files before integrating\nasync function cleanStaleGitLocks(localDir: string): Promise<void> {\n  const glob = await import(\"node:fs/promises\");\n  // Remove stale ref lock files older than 5 minutes\n  // (only safe when no other git process is running)\n}","typeGuard":null,"tryCatchPattern":"try {\n  await integrateImportedGitHead({ localDir, importedHead });\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"after multiple retries\")) {\n    // Lock contention persisted — serialize and retry after a delay\n    await cleanStaleGitLocks(localDir);\n    await integrateImportedGitHead({ localDir, importedHead });\n  } else {\n    throw err;\n  }\n}","preventionTips":["Serialize workspace sync operations with a mutex per localDir.","Clean up stale .git lock files after crashes.","Avoid running git gc/repack concurrently with workspace sync.","Use a local filesystem instead of NFS for workspace repos to reduce lock contention."],"tags":["git","workspace-sync","concurrency","lock-contention","adapter-utils"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}