{"record":{"id":"f7c9831d7ae12310","repo":"Yeachan-Heo/oh-my-codex","slug":"agent-name-must-not-be-empty","errorCode":null,"errorMessage":"agent name must not be empty","messagePattern":"agent name must not be empty","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/agents.ts","lineNumber":45,"sourceCode":"type AgentScope = 'user' | 'project';\n\nexport interface NativeAgentInfo {\n  scope: AgentScope;\n  path: string;\n  file: string;\n  name: string;\n  description: string;\n  model?: string;\n}\n\nfunction isReservedNativeAgentName(name: string): boolean {\n  return RESERVED_NATIVE_AGENT_NAMES.has(name.trim());\n}\n\nfunction normalizeAgentName(name: string): string {\n  const trimmed = name.trim();\n  if (!trimmed) {\n    throw new Error('agent name must not be empty');\n  }\n  if (!/^[A-Za-z0-9][A-Za-z0-9_-]*$/.test(trimmed)) {\n    throw new Error(`invalid agent name: ${name}`);\n  }\n  if (isReservedNativeAgentName(trimmed)) {\n    throw new Error(`\"${trimmed}\" is reserved by Codex built-in agents`);\n  }\n  return trimmed;\n}\n\nfunction resolveAgentsDir(scope: AgentScope, cwd = process.cwd()): string {\n  return scope === 'project' ? projectCodexAgentsDir(cwd) : codexAgentsDir();\n}\n\nfunction parseScopeArg(args: string[]): AgentScope | undefined {\n  for (let i = 0; i < args.length; i += 1) {\n    const arg = args[i];\n    if (arg === '--scope') {","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/agents.ts#L27-L63","documentation":"normalizeAgentName trims the agent name and rejects an empty/whitespace-only result. Every agent subcommand (add/edit/remove) normalizes names first, so this fires before any filesystem access.","triggerScenarios":"Calling addNativeAgent(''), addNativeAgent('   '), or a CLI invocation like `omx agent add \"\"` where the name comes from an empty variable.","commonSituations":"Unset/empty shell variables in scripts ($AGENT_NAME not exported), reading names from a config list with blank lines, or programmatic loops over sparse arrays.","solutions":["Check the name variable is set and non-empty before calling","Skip blank entries when iterating a list of names","Default to a concrete name in scripts"],"exampleFix":"# before\nomx agent add \"$AGENT_NAME\"  # AGENT_NAME unset -> ''\n\n# after\n[ -n \"$AGENT_NAME\" ] || { echo 'AGENT_NAME required'; exit 1; }\nomx agent add \"$AGENT_NAME\"","handlingStrategy":"validation","validationCode":"const name = String(rawName ?? '').trim();\nif (!name) {\n  console.error('agent name is required');\n  process.exit(2);\n}","typeGuard":"const isNonEmptyName = (n: unknown): n is string => typeof n === 'string' && n.trim().length > 0;","tryCatchPattern":null,"preventionTips":["Guard scripts with [ -n \"$AGENT_NAME\" ]","Filter blank lines when reading agent names from files"],"tags":["cli","validation","agents","empty-string"],"backgroundTag":"empty-required-field","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}