can1357/oh-my-pi · error

Model output is not a JSON object

Error message

Model output is not a JSON object

What it means

parseGeneratedAgentSpec takes the raw model output from the agent-creation architect, extracts a JSON object via extractJsonObject, and JSON.parses it. If the parsed value is null/falsy or not an object (e.g. the model emitted a JSON array, string, or number), this error is thrown. It is the first validation gate on LLM output before field-level checks run.

Source

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

			.trim();
		if (text.length > 0) return text;
	}
	return null;
}

function extractJsonObject(raw: string): string {
	const fenceMatch = raw.match(/```(?:json)?\s*([\s\S]*?)```/i);
	if (fenceMatch?.[1]) return fenceMatch[1].trim();
	const start = raw.indexOf("{");
	const end = raw.lastIndexOf("}");
	if (start >= 0 && end >= start) return raw.slice(start, end + 1).trim();
	return raw.trim();
}

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) {

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-run the architect with a stronger model or retry — this is usually a one-off model formatting failure.
  2. Tighten the architect prompt so it explicitly demands a single JSON object with the required keys and nothing else.
  3. Check the raw model output (logs) to see what was actually parsed and adjust extractJsonObject boundaries if the JSON is embedded in prose.

Example fix

// model output before: 'Here are your agents: ["a","b"]'
// after (prompt enforced single object):
// {"identifier":"code-reviewer","whenToUse":"Use this agent when...","systemPrompt":"..."}
Defensive patterns

Strategy: try-catch

Validate before calling

function looksLikeJsonObject(raw: string): boolean {
  const s = raw.trim();
  return s.startsWith("{") && s.endsWith("}");
}
if (!looksLikeJsonObject(raw)) retryArchitect();

Type guard

function isRecord(v: unknown): v is Record<string, unknown> {
  return typeof v === "object" && v !== null && !Array.isArray(v);
}

Try / catch

try {
  const spec = parseGeneratedAgentSpec(raw);
} catch (err) {
  if (err.message === "Model output is not a JSON object") {
    return retryArchitect({ stricterJsonInstruction: true });
  } throw err;
}

Prevention

When it happens

Trigger: #runAgentCreationArchitect receives model output where extractJsonObject yields text that JSON.parses to a non-object — e.g. the model wrapped output in prose that confuses extraction, or emitted a bare array/string/number.

Common situations: Weak or non-instructed models ignoring the JSON-only output format; truncated responses that still parse to a primitive; prompts edited so the JSON schema example was removed.

Related errors


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