{"record":{"id":"93fe4d047f4a7aec","repo":"google-gemini/gemini-cli","slug":"eexist","errorCode":"EEXIST","errorMessage":"Slug ${slug} is already owned by ${owner}","messagePattern":"Slug (.+?) is already owned by (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/config/projectRegistry.ts","lineNumber":391,"sourceCode":"    slug: string,\n    projectPath: string,\n  ): Promise<void> {\n    const normalizedProject = this.normalizePath(projectPath);\n    for (const baseDir of this.baseDirs) {\n      const slugDir = path.join(baseDir, slug);\n      if (!fs.existsSync(slugDir)) {\n        await fs.promises.mkdir(slugDir, { recursive: true });\n      }\n      const markerPath = path.join(slugDir, PROJECT_ROOT_FILE);\n      if (fs.existsSync(markerPath)) {\n        const owner = (await fs.promises.readFile(markerPath, 'utf8')).trim();\n        if (this.normalizePath(owner) === normalizedProject) {\n          continue;\n        }\n        // Collision!\n        const error = Object.assign(\n          new Error(`Slug ${slug} is already owned by ${owner}`),\n          { code: 'EEXIST' },\n        );\n        throw error;\n      }\n      // Use flag: 'wx' to ensure atomic creation\n      try {\n        await fs.promises.writeFile(markerPath, normalizedProject, {\n          encoding: 'utf8',\n          flag: 'wx',\n        });\n      } catch (e: unknown) {\n        if (isNodeError(e) && e.code === 'EEXIST') {\n          // Re-verify ownership in case we just lost a race\n          const owner = (await fs.promises.readFile(markerPath, 'utf8')).trim();\n          if (this.normalizePath(owner) === normalizedProject) {\n            continue;\n          }\n        }\n        throw e;","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/google-gemini/gemini-cli/blob/5024443c7217464a66e98f80d73172a26440bd8f/packages/core/src/config/projectRegistry.ts#L373-L409","documentation":"EEXIST 'Slug X is already owned by Y' is thrown by ensureOwnershipMarkers when a project-slug directory's PROJECT_ROOT_FILE marker already exists and points to a DIFFERENT normalized project path. The project registry uses these markers to map short slugs to absolute project paths; a mismatch means another project claimed the slug first.","triggerScenarios":"ensureOwnershipMarkers(slug, projectPath) reads markerPath; reads owner from it; normalizePath(owner) !== normalizePath(projectPath) -> throws Error with code:'EEXIST' at line 389-393. The caller (getOrAssignSlug) catches code==='EEXIST' or message includes 'already owned by' and retries the next candidate slug.","commonSituations":"Two sibling projects with similar directory names slugify to the same string (e.g. 'my-app' and 'My App'); stale marker left by a moved/renamed project directory; race when two CLI processes onboard different projects concurrently.","solutions":["Let the caller retry — getOrAssignSlug already advances to the next candidate on EEXIST; the error should be rare to surface.","Delete the stale marker directory (<baseDir>/<slug>/PROJECT_ROOT_FILE) for the old owner if the project was renamed/moved.","Rename one project so its slugify() output is unique."],"exampleFix":"# before: marker owned by /old/path\nrm -rf ~/.gemini/registry/my-app\n# after: next setupUser call reclaims the slug cleanly","handlingStrategy":"try-catch","validationCode":"// pre-check ownership before ensureOwnershipMarkers\nfor (const base of baseDirs) {\n  const marker = path.join(base, slug, PROJECT_ROOT_FILE);\n  if (fs.existsSync(marker) && fs.readFileSync(marker,'utf8').trim() !== normalize(projectPath)) {\n    return pickNextCandidate();\n  }\n}","typeGuard":"function isSlugCollision(e: unknown): boolean {\n  return isNodeError(e) && (e as NodeJS.ErrnoException).code === 'EEXIST'\n    || (e instanceof Error && e.message.includes('already owned by'));\n}","tryCatchPattern":"try { await registry.ensureOwnershipMarkers(slug, projectPath); }\ncatch (e) {\n  if (isSlugCollision(e)) { /* try next candidate slug */ continue; }\n  throw e;\n}","preventionTips":["Garbage-collect registry markers for renamed/moved projects.","Give sibling projects distinct directory names so slugify() differs."],"tags":["project-registry","slug-collision","filesystem","typescript"],"backgroundTag":null,"analyzedSha":"5024443c7217464a66e98f80d73172a26440bd8f","analyzedAt":"2026-08-12T06:01:53.711Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}