can1357/oh-my-pi · error

Generated identifier is invalid (must be lowercase kebab-cas

Error message

Generated identifier is invalid (must be lowercase kebab-case, 2+ words)

What it means

parseGeneratedAgentSpec validates the trimmed identifier against IDENTIFIER_PATTERN, which requires lowercase kebab-case with 2+ words (at least one hyphen). An identifier like 'Reviewer', 'reviewer', or 'x' fails the pattern and throws this error. It keeps generated agent ids consistent with the filesystem/config naming conventions used for agents.

Source

Thrown at packages/coding-agent/src/modes/components/agents-hub.ts:188

}

function parseGeneratedAgentSpec(raw: string): GeneratedAgentSpec {
	const parsed = JSON.parse(extractJsonObject(raw)) as Partial<GeneratedAgentSpec>;
	if (!parsed || typeof parsed !== "object") {
		throw new Error("Model output is not a JSON object");
	}
	if (
		typeof parsed.identifier !== "string" ||
		typeof parsed.whenToUse !== "string" ||
		typeof parsed.systemPrompt !== "string"
	) {
		throw new Error("Model output is missing required fields (identifier, whenToUse, systemPrompt)");
	}
	const identifier = parsed.identifier.trim();
	const whenToUse = parsed.whenToUse.trim();
	const systemPrompt = parsed.systemPrompt.trim();
	if (!IDENTIFIER_PATTERN.test(identifier)) {
		throw new Error("Generated identifier is invalid (must be lowercase kebab-case, 2+ words)");
	}
	if (!whenToUse.toLowerCase().startsWith("use this agent when")) {
		throw new Error("Generated whenToUse must start with 'Use this agent when...'");
	}
	if (!systemPrompt) {
		throw new Error("Generated systemPrompt is empty");
	}
	return { identifier, whenToUse, systemPrompt };
}

function matchAgent(agent: HubAgent, query: string): boolean {
	const text = `${agent.name} ${agent.description} ${SOURCE_LABEL[agent.source]} ${agent.overrideModel ?? ""}`;
	return query
		.trim()
		.split(/\s+/)
		.every(token => fuzzyMatch(token, text).matches);
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Retry the generation; if it repeats, state the naming constraint (lowercase kebab-case, two or more words) explicitly to the architect/user prompt.
  2. Sanitize/derive the identifier yourself from the description before invoking creation, and pass it as guidance.
  3. If validating locally before persisting, apply the same IDENTIFIER_PATTERN check to catch bad ids early.

Example fix

// before (model output)
{"identifier":"CodeReviewer", ...}
// after
{"identifier":"code-reviewer", ...}
Defensive patterns

Strategy: validation

Validate before calling

const IDENTIFIER_PATTERN = /^[a-z0-9]+(-[a-z0-9]+)+$/;
function identifierOk(id: string): boolean {
  return IDENTIFIER_PATTERN.test(id.trim());
}
if (!identifierOk(parsed.identifier)) parsed.identifier = slugify(parsed.description);

Type guard

function isKebabCaseMultiWord(v: unknown): v is string {
  return typeof v === "string" && /^[a-z0-9]+(-[a-z0-9]+)+$/.test(v);
}

Try / catch

try {
  const spec = parseGeneratedAgentSpec(raw);
} catch (err) {
  if (err.message.startsWith("Generated identifier is invalid")) {
    const fixed = { ...parsed(raw), identifier: slugify(parsed(raw).identifier) };
    return parseGeneratedAgentSpec(JSON.stringify(fixed));
  } throw err;
}

Prevention

When it happens

Trigger: #runAgentCreationArchitect receives a valid spec whose identifier violates the kebab-case/2-word rule — e.g. 'CodeReviewer' (uppercase), 'reviewer' (single word), 'code_reviewer' (underscore), or 'code--reviewer' style malformed ids.

Common situations: Models producing CamelCase or single-word names from the user's feature description; non-English descriptions leading to a single-token identifier; model echoing the user's verbatim agent name.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/de69c54374508eac. Report an issue: GitHub.