{"record":{"id":"0e328f5517309bba","repo":"run-llama/llama_index","slug":"key-should-not-be-none-0e328f","errorCode":null,"errorMessage":"key should not be None","messagePattern":"key should not be None","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/prompts/guidance_utils.py","lineNumber":110,"sourceCode":"    elif schema[\"type\"] == \"array\":\n        if key is None:\n            raise ValueError(\"Key should not be None\")\n        if \"max_items\" in schema:\n            extra_args = f\" max_iterations={schema['max_items']}\"\n        else:\n            extra_args = \"\"\n        return (\n            \"[{{#geneach '\"\n            + key\n            + \"' stop=']'\"\n            + extra_args\n            + \"}}{{#unless @first}}, {{/unless}}\"\n            + json_schema_to_guidance_output_template(schema[\"items\"], \"this\", 0, root)\n            + \"{{/geneach}}]\"\n        )\n    elif schema[\"type\"] == \"string\":\n        if key is None:\n            raise ValueError(\"key should not be None\")\n        return \"\\\"{{gen '\" + key + \"' stop='\\\"'}}\\\"\"\n    elif schema[\"type\"] in [\"integer\", \"number\"]:\n        if key is None:\n            raise ValueError(\"key should not be None\")\n        if use_pattern_control:\n            return \"{{gen '\" + key + \"' pattern='[0-9\\\\.]' stop=','}}\"\n        else:\n            return \"\\\"{{gen '\" + key + \"' stop='\\\"'}}\\\"\"\n    elif schema[\"type\"] == \"boolean\":\n        if key is None:\n            raise ValueError(\"key should not be None\")\n        return \"{{#select '\" + key + \"'}}True{{or}}False{{/select}}\"\n    else:\n        schema_type = schema[\"type\"]\n        raise ValueError(f\"Unknown schema type {schema_type}\")\n\n\nModel = TypeVar(\"Model\", bound=BaseModel)","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/prompts/guidance_utils.py#L92-L128","documentation":"Raised by llama-index's guidance integration (json_schema_to_guidance_output_template in prompts/guidance_utils.py) when the JSON schema walker hits a 'string' node at a position where no variable key exists (key is None). Guidance programs can only emit a string via a {{gen 'key'}} command, so a top-level bare string schema (e.g. a pydantic model whose root is just str) cannot be compiled into a guidance template. The library assumes real-world structured outputs are objects, so it hard-fails on anything else.","triggerScenarios":"Calling GuidancePydanticProgram (or anything that builds a guidance template from a pydantic model) with an output_class whose JSON schema root type is 'string' — e.g. `class Out(BaseModel): __root__: str` in pydantic v1 or a RootModel[str] in v2. The recursive schema compiler is invoked with key=None at the root, hits schema['type'] == 'string', and raises.","commonSituations":"Migrating a simple prompt that used to return raw text to a 'structured' pydantic output, defining a wrapper model that is just a single string field at the root, or passing List[str]-style roots that nest down to bare scalars. Also appears with older guidance versions where llama-index's guidance support was only ever tested against object models.","solutions":["Wrap the scalar in a real object model, e.g. `class Out(BaseModel): answer: str` (pydantic) instead of a bare str root, then read `.answer` after parsing.","If you only need plain text back, skip the guidance/structured-program path and call the LLM directly instead of GuidancePydanticProgram.","Switch to a structured-output mechanism that supports scalar roots (e.g. an LLM provider with native JSON/function-call output), since guidance support here is deprecated anyway.","If you must keep the model shape, pre-check the schema root type (see validation) before constructing the program so you fail with your own clearer error."],"exampleFix":"// before\nfrom pydantic import BaseModel\nclass Answer(BaseModel):\n    __root__: str  # root type 'string' -> ValueError\nprogram = GuidancePydanticProgram(output_class=Answer, ...)\n\n// after\nfrom pydantic import BaseModel\nclass Answer(BaseModel):\n    answer: str  # root type 'object' -> template compiles\nprogram = GuidancePydanticProgram(output_class=Answer, ...)\nresult = program(...).answer","handlingStrategy":"validation","validationCode":"from pydantic import BaseModel\n\ndef assert_guidance_compatible(cls: type[BaseModel]) -> None:\n    schema = cls.model_json_schema()  # pydantic v2; .schema() on v1\n    if schema.get(\"type\") != \"object\":\n        raise TypeError(\n            f\"{cls.__name__} has root type {schema.get('type')!r}; \"\n            \"GuidancePydanticProgram requires an object-rooted model \"\n            \"(wrap scalars in a named field).\"\n        )\n\nassert_guidance_compatible(Answer)  # run before building the program","typeGuard":"def is_object_rooted_model(cls) -> bool:\n    \"\"\"True when cls compiles to a guidance-compatible object schema.\"\"\"\n    try:\n        schema = cls.model_json_schema()\n    except Exception:\n        return False\n    return schema.get(\"type\") == \"object\"","tryCatchPattern":null,"preventionTips":["Always wrap scalar outputs in a named pydantic field instead of using __root__/RootModel for guidance programs.","Add a startup assertion on model_json_schema()['type'] == 'object' before constructing GuidancePydanticProgram.","Prefer provider-native structured output over the deprecated guidance integration for new code."],"tags":["llama-index","guidance","pydantic","json-schema","structured-output"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}