{"record":{"id":"594e8b6a5c26ca5a","repo":"run-llama/llama_index","slug":"no-valid-json-found-in-output-output","errorCode":null,"errorMessage":"No valid JSON found in output: {output}","messagePattern":"No valid JSON found in output: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/question_gen/output_parser.py","lineNumber":13,"sourceCode":"from typing import Any\n\nfrom llama_index.core.output_parsers.base import StructuredOutput\nfrom llama_index.core.output_parsers.utils import parse_json_markdown\nfrom llama_index.core.question_gen.types import SubQuestion\nfrom llama_index.core.types import BaseOutputParser\n\n\nclass SubQuestionOutputParser(BaseOutputParser):\n    def parse(self, output: str) -> Any:\n        json_dict = parse_json_markdown(output)\n        if not json_dict:\n            raise ValueError(f\"No valid JSON found in output: {output}\")\n\n        # example code includes an 'items' key, which breaks\n        # the parsing from open-source LLMs such as Zephyr.\n        # This gets the actual subquestions and recommended tools directly\n        if \"items\" in json_dict:\n            json_dict = json_dict[\"items\"]\n\n        sub_questions = [SubQuestion.model_validate(item) for item in json_dict]\n        return StructuredOutput(raw_output=output, parsed_output=sub_questions)\n\n    def format(self, prompt_template: str) -> str:\n        return prompt_template\n","sourceCodeStart":1,"sourceCodeEnd":26,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/question_gen/output_parser.py#L1-L26","documentation":"SubQuestionOutputParser.parse() runs parse_json_markdown over the LLM output and expects a JSON array/object of sub-questions. If no JSON can be extracted (falsy result), it raises ValueError('No valid JSON found in output: {output}') before validating SubQuestion items (an 'items' wrapper key is unwrapped first for models like Zephyr).","triggerScenarios":"LLMQuestionGenerator with a model whose output deviates from the DEFAULT_SUB_QUESTION_PROMPT format — pure prose, truncated JSON, or markdown that parse_json_markdown cannot recover JSON from.","commonSituations":"Small/local models (Zephyr, Llama variants) ignoring the JSON schema, aggressive max_tokens truncating the JSON, or a custom prompt that no longer asks for JSON.","solutions":["Use a stronger instruction-following LLM, or an OpenAI function-calling model via OpenAIQuestionGenerator","Raise max_tokens / output length so the JSON array is not truncated","If using a custom prompt_template_str, preserve the JSON structure and {output_cls} placeholder from the default","Catch ValueError in the query pipeline and retry the sub-question generation once"],"exampleFix":"// before\ngen = LLMQuestionGenerator.from_defaults(llm=weak_local_llm)\nsqe = SubQuestionQueryEngine(query_engine_tools=tools, question_gen=gen)\nresp = sqe.query(q)  # raises on non-JSON output\n\n// after\ngen = LLMQuestionGenerator.from_defaults(\n    llm=OpenAI(model=\"gpt-4o-mini\")  # follows JSON format reliably\n)\nsqe = SubQuestionQueryEngine(query_engine_tools=tools, question_gen=gen)\nresp = sqe.query(q)","handlingStrategy":"try-catch","validationCode":"# cheap pre-flight: ask the same model to emit JSON for a trivial prompt and try parsing it\nfrom llama_index.core.output_parsers.utils import parse_json_markdown\n\nprobe = llm.complete(\"Return exactly this JSON: [{\\\"q\\\": \\\"hi\\\"}]\")\nif not parse_json_markdown(probe.text):\n    raise RuntimeError(\"LLM cannot produce parseable JSON; sub-question parsing will fail\")","typeGuard":null,"tryCatchPattern":"try:\n    resp = sub_question_engine.query(q)\nexcept ValueError as e:\n    if \"No valid JSON found in output\" in str(e):\n        resp = sub_question_engine.query(q)  # retry once; JSON adherence is nondeterministic\n    else:\n        raise","preventionTips":["Use function-calling models (OpenAIQuestionGenerator) when available","Raise max_tokens so JSON output is never truncated","Reuse DEFAULT_SUB_QUESTION_PROMPT_TMPL structure in custom prompts","Add one retry around sub-question queries in production paths"],"tags":["json","parsing","llm-output","sub-question"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}