Yeachan-Heo/oh-my-codex · error · Error
Invalid team_name: "${rawTeamName}". Must match /^[a-z0-9][a
Error message
Invalid team_name: "${rawTeamName}". Must match /^[a-z0-9][a-z0-9-]{0,29}$/ or resolve to an existing display name. What it means
Thrown during display-name resolution: the team_name neither matches the strict safe pattern nor resolves to any known display/requested name in the current workspace (via listTeamLookupCandidates). It means the team is unknown to this repository's state.
Source
Thrown at src/team/api-interop.ts:604
function normalizeTeamDisplayLookupName(value: string): string {
return value
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '')
.slice(0, 30)
.replace(/-$/, '');
}
function assertUnsafeTeamNameMatchesKnownDisplay(rawTeamName: string, cwd: string): void {
if (TEAM_NAME_SAFE_PATTERN.test(rawTeamName)) return;
const normalized = normalizeTeamDisplayLookupName(rawTeamName);
const matchesKnownDisplay = listTeamLookupCandidates(cwd).some((candidate) => {
return normalizeTeamDisplayLookupName(candidate.displayName) === normalized
|| normalizeTeamDisplayLookupName(candidate.requestedName) === normalized;
});
if (!matchesKnownDisplay) {
throw new Error(`Invalid team_name: "${rawTeamName}". Must match /^[a-z0-9][a-z0-9-]{0,29}$/ or resolve to an existing display name.`);
}
}
export async function executeTeamApiOperation(
operation: TeamApiOperation,
args: Record<string, unknown>,
fallbackCwd: string,
): Promise<TeamApiEnvelope> {
try {
validateCommonFields(args, { skipTeamName: true });
const rawTeamNameForCwd = String(args.team_name || '').trim();
if (rawTeamNameForCwd) assertUnsafeTeamNameMatchesKnownDisplay(rawTeamNameForCwd, fallbackCwd);
const resolvedTeamName = rawTeamNameForCwd ? resolveTeamNameForCurrentContext(rawTeamNameForCwd, fallbackCwd) : '';
const cwd = resolvedTeamName ? resolveTeamWorkingDirectory(resolvedTeamName, fallbackCwd) : fallbackCwd;
const opArgs = resolvedTeamName ? { ...args, team_name: resolvedTeamName } : args;
validateCommonFields(opArgs);
switch (operation) {View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Run from the repository root where the team state exists
- List available team lookup candidates to find the exact accepted name
- Fall back to the team's canonical slug matching the safe pattern
Example fix
// before
api('status', { team_name: 'My Team' }); // unknown in this cwd
// after
const cands = listTeamLookupCandidates(cwd); // pick exact displayName
api('status', { team_name: cands[0].displayName }); Defensive patterns
Strategy: fallback
Validate before calling
const known = listTeamLookupCandidates(cwd);
const ok = /^[a-z0-9][a-z0-9-]{0,29}$/.test(name)
|| known.some((c) => c.displayName === name || c.requestedName === name);
if (!ok) throw new Error('unknown team name'); Try / catch
catch (e) { if (/or resolve to an existing display name/.test(e.message)) { const cands = listTeamLookupCandidates(cwd); /* pick or create team */ } } Prevention
- Always run team operations from the repo root holding team state
- Cache the canonical team slug at creation time and reuse it
When it happens
Trigger: Passing a human-readable team name that was never registered/persisted in the workspace, or a typo, or running from the wrong cwd where the team candidates are not listed.
Common situations: Running the API from a different working directory than where the team was created; stale workspace state after cleanup; typo in display name casing/punctuation.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/9623a7a47d5709e1.
Report an issue: GitHub.