{"record":{"id":"ed93c845861ff977","repo":"BerriAI/litellm","slug":"litellm-jsonschemavalidationerror-model-model","errorCode":null,"errorMessage":"litellm.JSONSchemaValidationError: model={model}, returned an invalid response={raw_response}, for schema={schema}.\\nAccess raw response with `e.raw_response`","messagePattern":"litellm\\.JSONSchemaValidationError: model=(.+?), returned an invalid response=(.+?), for schema=(.+?)\\.\\\\nAccess raw response with `e\\.raw_response`","errorType":"validation","errorClass":"JSONSchemaValidationError","httpStatus":500,"severity":"error","filePath":"litellm/litellm_core_utils/json_validation_rule.py","lineNumber":114,"sourceCode":"    return normalized_tool\n\n\ndef validate_schema(schema: dict, response: str):\n    \"\"\"\n    Validate if the returned json response follows the schema.\n\n    Params:\n    - schema - dict: JSON schema\n    - response - str: Received json response as string.\n    \"\"\"\n    from jsonschema import ValidationError, validate\n\n    from litellm import JSONSchemaValidationError\n\n    try:\n        response_dict: Final = json.loads(response)\n    except json.JSONDecodeError:\n        raise JSONSchemaValidationError(model=\"\", llm_provider=\"\", raw_response=response, schema=json.dumps(schema))\n\n    try:\n        validate(response_dict, schema=schema)\n    except ValidationError:\n        raise JSONSchemaValidationError(model=\"\", llm_provider=\"\", raw_response=response, schema=json.dumps(schema))\n","sourceCodeStart":96,"sourceCodeEnd":120,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/litellm_core_utils/json_validation_rule.py#L96-L120","documentation":"Raised by validate_schema() (called from litellm.utils during response post-processing) when response-format enforcement is enabled and the completion text cannot even be parsed as JSON: json.loads() raises JSONDecodeError and LiteLLM converts it into JSONSchemaValidationError with model/llm_provider empty but raw_response and schema attached. Enforcement is on when litellm.enable_json_schema_validation is True (or per-request enable_json_schema_validation) with a response_format json_schema/Pydantic model, or response_format has enforce_validation: True. Access the offending text via e.raw_response.","triggerScenarios":"litellm.completion(..., mock_response='some non-json text', response_format=<Pydantic model or {'type':'json_schema','json_schema':...}>) with validation enabled — the classic unit-test case; or any path feeding a non-JSON string into a validated response_format. The two call sites are in the mock-response post-processing in litellm/utils.py.","commonSituations":"Tests using mock_response strings ('hello', prose answers) while response_format expects structured output; mocks written before response_format was added; enabling enable_json_schema_validation globally and forgetting mocks must now be valid JSON.","solutions":["Make the supplied/mocked response a JSON string: json.dumps({...}).","For Pydantic response_format, build the mock from the model: json.dumps(MyModel(...).model_dump()).","Catch litellm.JSONSchemaValidationError and inspect e.raw_response / e.schema to see exactly what failed.","Disable enforcement where validation is not wanted (drop enforce_validation or enable_json_schema_validation for that call/test)."],"exampleFix":"# before\nlitellm.completion(model='gpt-4o', messages=m, response_format=MyModel, mock_response='sure thing!')\n\n# after\nimport json\nlitellm.completion(model='gpt-4o', messages=m, response_format=MyModel, mock_response=json.dumps(MyModel(name='x', age=1).model_dump()))","handlingStrategy":"try-catch","validationCode":"import json\n\nif isinstance(mock_response, str):\n    try:\n        json.loads(mock_response)\n    except json.JSONDecodeError:\n        mock_response = json.dumps({'field': mock_response})  # or build from the Pydantic model\nresp = litellm.completion(model='gpt-4o', messages=m, response_format=MyModel, mock_response=mock_response)","typeGuard":null,"tryCatchPattern":"import litellm\n\ntry:\n    resp = litellm.completion(model='gpt-4o', messages=m, response_format=MyModel, mock_response=mock_response)\nexcept litellm.JSONSchemaValidationError as e:\n    raw = e.raw_response  # inspect the offending text\n    fixed = json.dumps(MyModel(name='x', age=1).model_dump())\n    resp = litellm.completion(model='gpt-4o', messages=m, response_format=MyModel, mock_response=fixed)","preventionTips":["Generate structured-output mocks from the Pydantic model itself so they always parse.","Keep mocks and response_format models in the same module so renames stay in sync.","Run a tiny json.loads() assert over mock fixtures in CI."],"tags":["litellm","structured-output","json-schema","mock-response","validation"],"backgroundTag":"invalid-json-response","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}