{"record":{"id":"3e7c791e38af8dc8","repo":"Yeachan-Heo/oh-my-codex","slug":"agent-already-exists-path","errorCode":null,"errorMessage":"agent already exists: ${path}","messagePattern":"agent already exists: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/agents.ts","lineNumber":174,"sourceCode":"): Promise<NativeAgentInfo[]> {\n  if (scope) return readScopeAgents(scope, cwd);\n  const [projectAgents, userAgents] = await Promise.all([\n    readScopeAgents('project', cwd),\n    readScopeAgents('user', cwd),\n  ]);\n  return [...projectAgents, ...userAgents].sort((a, b) => a.name.localeCompare(b.name) || a.scope.localeCompare(b.scope));\n}\n\nasync function addNativeAgent(\n  name: string,\n  options: { cwd?: string; scope?: AgentScope; force?: boolean } = {},\n): Promise<string> {\n  const cwd = options.cwd ?? process.cwd();\n  const scope = options.scope ?? inferMutationScope(cwd);\n  const normalized = normalizeAgentName(name);\n  const path = getAgentFilePath(normalized, scope, cwd);\n  if (existsSync(path) && !options.force) {\n    throw new Error(`agent already exists: ${path}`);\n  }\n  await mkdir(resolveAgentsDir(scope, cwd), { recursive: true });\n  await writeFile(path, scaffoldAgentToml(normalized));\n  return path;\n}\n\nfunction resolveExistingAgentPath(\n  name: string,\n  options: { cwd?: string; scope?: AgentScope } = {},\n): string {\n  const cwd = options.cwd ?? process.cwd();\n  const normalized = normalizeAgentName(name);\n  const candidateScopes: AgentScope[] = options.scope ? [options.scope] : ['project', 'user'];\n  for (const scope of candidateScopes) {\n    const path = getAgentFilePath(normalized, scope, cwd);\n    if (existsSync(path)) return path;\n  }\n  throw new Error(`agent not found: ${normalized}`);","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/agents.ts#L156-L192","documentation":"addNativeAgent refuses to overwrite an existing agent file at the resolved path unless options.force is true. The path depends on scope: project scope resolves under .codex/agents in the repo, user scope under the home directory.","triggerScenarios":"Running the same `agent add` twice, or adding an agent whose TOML file already exists in the chosen scope.","commonSituations":"Re-running scaffolding scripts, agents created by teammates and pulled via git (project scope), or forgetting a previous add succeeded.","solutions":["Pass --force to overwrite the existing agent file","Choose a different agent name","Remove the existing agent first (agent remove)"],"exampleFix":"# before\nomx agent add reviewer\n\n# after\nomx agent add reviewer --force","handlingStrategy":"try-catch","validationCode":"import { existsSync } from 'node:fs';\nif (existsSync(path) && !force) {\n  // decide: overwrite with force:true, pick another name, or abort\n}","typeGuard":null,"tryCatchPattern":"try {\n  await addNativeAgent(name, { force: shouldOverwrite });\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('agent already exists:')) {\n    await addNativeAgent(name, { force: true }); // deliberate overwrite\n  } else throw e;\n}","preventionTips":["Make scaffolding scripts idempotent by passing --force when overwrite is intended","Check existence first and branch on it","Use unique per-team agent names to avoid project-scope collisions from git"],"tags":["cli","agents","file-exists","idempotency"],"backgroundTag":"file-already-exists","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}