{"record":{"id":"944260874175941a","repo":"can1357/oh-my-pi","slug":"model-output-is-not-a-json-object","errorCode":null,"errorMessage":"Model output is not a JSON object","messagePattern":"Model output is not a JSON object","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/modes/components/agents-hub.ts","lineNumber":175,"sourceCode":"\t\t\t.trim();\n\t\tif (text.length > 0) return text;\n\t}\n\treturn null;\n}\n\nfunction extractJsonObject(raw: string): string {\n\tconst fenceMatch = raw.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n\tif (fenceMatch?.[1]) return fenceMatch[1].trim();\n\tconst start = raw.indexOf(\"{\");\n\tconst end = raw.lastIndexOf(\"}\");\n\tif (start >= 0 && end >= start) return raw.slice(start, end + 1).trim();\n\treturn raw.trim();\n}\n\nfunction parseGeneratedAgentSpec(raw: string): GeneratedAgentSpec {\n\tconst parsed = JSON.parse(extractJsonObject(raw)) as Partial<GeneratedAgentSpec>;\n\tif (!parsed || typeof parsed !== \"object\") {\n\t\tthrow new Error(\"Model output is not a JSON object\");\n\t}\n\tif (\n\t\ttypeof parsed.identifier !== \"string\" ||\n\t\ttypeof parsed.whenToUse !== \"string\" ||\n\t\ttypeof parsed.systemPrompt !== \"string\"\n\t) {\n\t\tthrow new Error(\"Model output is missing required fields (identifier, whenToUse, systemPrompt)\");\n\t}\n\tconst identifier = parsed.identifier.trim();\n\tconst whenToUse = parsed.whenToUse.trim();\n\tconst systemPrompt = parsed.systemPrompt.trim();\n\tif (!IDENTIFIER_PATTERN.test(identifier)) {\n\t\tthrow new Error(\"Generated identifier is invalid (must be lowercase kebab-case, 2+ words)\");\n\t}\n\tif (!whenToUse.toLowerCase().startsWith(\"use this agent when\")) {\n\t\tthrow new Error(\"Generated whenToUse must start with 'Use this agent when...'\");\n\t}\n\tif (!systemPrompt) {","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/modes/components/agents-hub.ts#L157-L193","documentation":"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.","triggerScenarios":"#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.","commonSituations":"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.","solutions":["Re-run the architect with a stronger model or retry — this is usually a one-off model formatting failure.","Tighten the architect prompt so it explicitly demands a single JSON object with the required keys and nothing else.","Check the raw model output (logs) to see what was actually parsed and adjust extractJsonObject boundaries if the JSON is embedded in prose."],"exampleFix":"// model output before: 'Here are your agents: [\"a\",\"b\"]'\n// after (prompt enforced single object):\n// {\"identifier\":\"code-reviewer\",\"whenToUse\":\"Use this agent when...\",\"systemPrompt\":\"...\"}","handlingStrategy":"try-catch","validationCode":"function looksLikeJsonObject(raw: string): boolean {\n  const s = raw.trim();\n  return s.startsWith(\"{\") && s.endsWith(\"}\");\n}\nif (!looksLikeJsonObject(raw)) retryArchitect();","typeGuard":"function isRecord(v: unknown): v is Record<string, unknown> {\n  return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  const spec = parseGeneratedAgentSpec(raw);\n} catch (err) {\n  if (err.message === \"Model output is not a JSON object\") {\n    return retryArchitect({ stricterJsonInstruction: true });\n  } throw err;\n}","preventionTips":["Prompt the model for a single JSON object and nothing else; show the exact schema.","Use structured output / JSON mode when the provider supports it.","Log raw model output so malformed responses are diagnosable."],"tags":["llm-output","json","validation","agents"],"backgroundTag":"llm-output-not-valid-json","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}