{"record":{"id":"47e8bc004103fce8","repo":"run-llama/llama_index","slug":"failed-to-parse-pydantic-object-from-guidance-prog","errorCode":null,"errorMessage":"Failed to parse pydantic object from guidance program. Probably the LLM failed to produce data with right json schema","messagePattern":"Failed to parse pydantic object from guidance program\\. Probably the LLM failed to produce data with right json schema","errorType":"exception","errorClass":"OutputParserException","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/prompts/guidance_utils.py","lineNumber":155,"sourceCode":"    This is a temporary solution for parsing a pydantic object out of an executed\n    guidance program.\n\n    NOTE: right now we assume the output is the last markdown formatted json block\n\n    NOTE: a better way is to extract via Program.variables, but guidance does not\n          support extracting nested objects right now.\n          So we call back to manually parsing the final text after program execution\n    \"\"\"\n    try:\n        output = response.split(\"```json\")[-1]\n        output = \"```json\" + output\n        if verbose:\n            print(\"Raw output:\")\n            print(output)\n        json_dict = parse_json_markdown(output)\n        sub_questions = cls.model_validate(json_dict)\n    except Exception as e:\n        raise OutputParserException(\n            \"Failed to parse pydantic object from guidance program\"\n            \". Probably the LLM failed to produce data with right json schema\"\n        ) from e\n    return sub_questions\n","sourceCodeStart":137,"sourceCodeEnd":160,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/prompts/guidance_utils.py#L137-L160","documentation":"OutputParserException from parse_pydantic_from_guidance_program: after a guidance program executes, llama-index re-extracts the JSON by splitting on the '```json' fence and running parse_json_markdown, then validates it against your pydantic class. Any failure anywhere in that chain (no fence found, truncated JSON, wrong field names/types) is swallowed and re-raised as this single generic message with the original exception chained via `from e`.","triggerScenarios":"GuidancePydanticProgram(...) where the executed program output lacks a '```json' block, the JSON is malformed/truncated by a token limit, the LLM emitted fields that fail cls.model_validate (missing required fields, wrong types), or the whole response is empty because the guidance template never executed (misconfigured llm).","commonSituations":"Low max_tokens cutting the JSON mid-object; using a weak local model that does not respect the guidance template; pydantic v1 vs v2 mismatch between the model and validation call; prompt/template edits that break the markdown fence the parser hard-codes on.","solutions":["Re-run with verbose=True in parse (or print the raw program output) to see exactly what the LLM produced — the chained exception (`__cause__`) usually names the real pydantic validation error.","Raise the LLM's max_tokens / num_output so the JSON block is never truncated.","Make the pydantic model lenient: give fields defaults, make them Optional with validators, so minor schema drift still validates.","Switch to a model/provider that follows the guidance template reliably, or move to native function-calling structured output where correctness is enforced by the API."],"exampleFix":"// before\nresult = program(..., verbose=False)  # fails opaquely\n\n// after\nfrom llama_index.core.output_parsers import OutputParserException\ntry:\n    result = program(..., verbose=True)  # prints raw output before parsing\nexcept OutputParserException as e:\n    print(\"cause:\", e.__cause__)         # real pydantic/json error\n    raise","handlingStrategy":"try-catch","validationCode":"def looks_like_guidance_json(response: str) -> bool:\n    \"\"\"Cheap pre-check that the executed program emitted a fenced JSON block.\"\"\"\n    return \"```json\" in response and response.rstrip().endswith(\"```\")","typeGuard":null,"tryCatchPattern":"from llama_index.core.output_parsers import OutputParserException\n\nfor attempt in range(3):\n    try:\n        result = program(dry_run=False, verbose=True)\n        break\n    except OutputParserException as e:\n        if attempt == 2:\n            raise\n        cause = e.__cause__ or e\n        print(f\"attempt {attempt} failed: {cause}\")  # real pydantic/json error\n        # optionally raise max_tokens or simplify the model, then retry","preventionTips":["Run with verbose=True while developing to see the raw LLM output before parsing.","Inspect e.__cause__ — the chained exception carries the actual pydantic validation error.","Give every output-model field a default so partially-formed JSON still validates.","Set generous max_tokens; truncation is the most common cause of unparseable fenced JSON."],"tags":["llama-index","guidance","output-parsing","pydantic","json","llm-output"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}