{"record":{"id":"9212a17b02cb39f1","repo":"ruvnet/ruflo","slug":"invalid-worktree-registry-record","errorCode":null,"errorMessage":"invalid worktree registry record","messagePattern":"invalid worktree registry record","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/codex/src/worktrees/coordinator.ts","lineNumber":104,"sourceCode":"        assignments,\n      };\n      this.writeRecord(registryPath, record);\n      return record;\n    } catch (error) {\n      for (const assignment of assignments.reverse()) {\n        try { git(this.repoRoot, ['worktree', 'remove', assignment.path]); } catch { /* retain work for recovery */ }\n      }\n      throw error;\n    }\n  }\n\n  status(runId: string): WorktreeRunRecord {\n    assertId(runId, 'run id');\n    const file = this.registryPath(runId);\n    if (!existsSync(file)) throw new Error(`unknown worktree run: ${runId}`);\n    const record = JSON.parse(readFileSync(file, 'utf8')) as WorktreeRunRecord;\n    if (record.version !== 1 || record.runId !== runId || resolve(record.repoRoot) !== this.repoRoot) {\n      throw new Error('invalid worktree registry record');\n    }\n    const expectedPrefix = resolve(join(this.worktreeBase, runId));\n    for (const assignment of record.assignments) {\n      const actual = resolve(assignment.path);\n      if (actual !== expectedPrefix && !actual.startsWith(`${expectedPrefix}/`)) {\n        throw new Error(`registry path escapes owned worktree root: ${actual}`);\n      }\n    }\n    return record;\n  }\n\n  integrate(runId: string, agentIds?: string[]): { merged: string[] } {\n    const record = this.status(runId);\n    const wanted = agentIds ? new Set(agentIds) : null;\n    const merged: string[] = [];\n    for (const assignment of record.assignments) {\n      if (assignment.readOnly || (wanted && !wanted.has(assignment.agentId))) continue;\n      git(this.repoRoot, ['merge', '--no-ff', '--no-edit', assignment.branch]);","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/ruvnet/ruflo/blob/fa13ee4ad60ac2090b1480656eb233521790d640/v3/@claude-flow/codex/src/worktrees/coordinator.ts#L86-L122","documentation":"After parsing the registry JSON, status() requires record.version === 1, record.runId === the requested run id, and resolve(record.repoRoot) === the coordinator's own repoRoot. Any mismatch means the file is corrupt, was written by an incompatible coordinator version, or belongs to a different repository, and the whole record is rejected as invalid.","triggerScenarios":"Hand-editing or truncating <runId>.json; a record written by a coordinator version using a different version field; copying .claude-flow/swarm/worktrees between repos or machines so record.repoRoot no longer matches; renaming the registry file to a different run id than the one stored inside.","commonSituations":"Upgrading @claude-flow/codex across registry-format changes; accidentally committing the registry directory and sharing it between clones; two coordinator instances constructed with different repoRoot paths.","solutions":["Delete the stale registry file (and any leftover worktrees under the sibling .ruflo-worktrees directory) and re-prepare the run with the same or a new run id","Construct CodexWorktreeCoordinator with the exact git top-level repoRoot that originally created the record","Treat registry JSON as internal coordinator state: never hand-edit, commit, or move it between repositories"],"exampleFix":"// before\nconst c = new CodexWorktreeCoordinator('/repo-clone-b');\nc.status('run-1'); // throws: invalid worktree registry record (repoRoot mismatch)\n\n// after\nconst c = new CodexWorktreeCoordinator('/repo-clone-a'); // same root that prepared the run\nc.status('run-1');","handlingStrategy":"try-catch","validationCode":"import { readFileSync, existsSync } from 'node:fs';\nfunction registryLooksValid(file: string, runId: string, repoRoot: string): boolean {\n  if (!existsSync(file)) return false;\n  try {\n    const r = JSON.parse(readFileSync(file, 'utf8'));\n    return r.version === 1 && r.runId === runId && resolve(r.repoRoot) === resolve(repoRoot);\n  } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  const record = coordinator.status(runId);\n} catch (e) {\n  if (e instanceof Error && e.message === 'invalid worktree registry record') {\n    // registry is corrupt/foreign: clean up this run's files and re-prepare\n    // (remove <runId>.json and the run's worktree dir), or start a new run id\n  } else throw e;\n}","preventionTips":["Pin one @claude-flow/codex version per repo to avoid registry-format drift","Never copy or commit .claude-flow/swarm/worktrees between machines or repositories"],"tags":["worktrees","registry","corruption","version-mismatch"],"backgroundTag":"corrupt-state-file","analyzedSha":"fa13ee4ad60ac2090b1480656eb233521790d640","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}