Yeachan-Heo/oh-my-codex · error · Error

[ask] invalid --agent-prompt role "${role}". Expected lowerc

Error message

[ask] invalid --agent-prompt role "${role}". Expected lowercase role names like "executor" or "test-engineer".

What it means

`omx ask --agent-prompt <role>` validates the role against SAFE_ROLE_PATTERN (lowercase alphanumeric/hyphen names) before touching the filesystem, as a path-traversal guard. Any role containing uppercase, slashes, dots, or other characters fails immediately with this error.

Source

Thrown at src/cli/ask.ts:63

      const parsed = JSON.parse(readFileSync(scopePath, 'utf-8')) as Partial<{ scope: string }>;
      if (parsed.scope === 'project' || parsed.scope === 'project-local') {
        return join(cwd, '.codex', 'prompts');
      }
    }
  } catch {
    // Ignore malformed persisted scope and fall back to user prompts.
  }

  return codexPromptsDir();
}

async function resolveAgentPromptContent(
  role: string,
  promptsDir: string,
): Promise<string> {
  const normalizedRole = role.trim().toLowerCase();
  if (!SAFE_ROLE_PATTERN.test(normalizedRole)) {
    throw new Error(`[ask] invalid --agent-prompt role "${role}". Expected lowercase role names like "executor" or "test-engineer".`);
  }

  if (!existsSync(promptsDir)) {
    throw new Error(`[ask] prompts directory not found: ${promptsDir}. Run "omx setup" to install prompts.`);
  }

  const promptPath = join(promptsDir, `${normalizedRole}.md`);
  if (!existsSync(promptPath)) {
    const files = await readdir(promptsDir).catch(() => [] as string[]);
    const availableRoles = files
      .filter((file) => file.endsWith('.md'))
      .map((file) => file.slice(0, -3))
      .sort();
    const availableSuffix = availableRoles.length > 0
      ? ` Available roles: ${availableRoles.join(', ')}.`
      : '';
    throw new Error(`[ask] --agent-prompt role "${normalizedRole}" not found in ${promptsDir}.${availableSuffix}`);
  }

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Use lowercase hyphenated role names, e.g. `--agent-prompt executor` or `--agent-prompt test-engineer`
  2. Trim whitespace and remove special characters from the role string in calling scripts
  3. Sanitize user-supplied roles before passing them: lowercase and strip invalid characters

Example fix

# before
omx ask --agent-prompt "Test Engineer" "do work"
# after
omx ask --agent-prompt test-engineer "do work"
Defensive patterns

Strategy: validation

Validate before calling

const SAFE = /^[a-z0-9]+(-[a-z0-9]+)*$/;
const role = String(rawRole).trim().toLowerCase();
if (!SAFE.test(role)) throw new Error('role must be lowercase-hyphen');

Type guard

const isSafeRole = (r: string): r is string => /^[a-z0-9]+(-[a-z0-9]+)*$/.test(r.trim());

Try / catch

catch (e) { if (/invalid --agent-prompt role/.test(String(e))) { promptUserForValidRole(); } else throw e; }

Prevention

When it happens

Trigger: Passing `--agent-prompt Executor`, `--agent-prompt ../secrets`, `--agent-prompt test_engineer` (underscore if not allowed), or any role that does not match the safe-name regex.

Common situations: Users typing natural role names with capitals or spaces; scripts interpolating user input into the flag; attempted path traversal via the role argument.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/e4c831de2f7363d6. Report an issue: GitHub.