{"record":{"id":"d529591956bef668","repo":"conductor-oss/conductor","slug":"error-e-getmessage-response-responsetext","errorCode":null,"errorMessage":"{\"error\":{e.getMessage()},\"response\":{responseText}}","messagePattern":"(.+?),\"response\":(.+?)\\}","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"ai/src/main/java/org/conductoross/conductor/ai/LLMHelper.java","lineNumber":317,"sourceCode":"                if (error != null) {\n                    throw new RuntimeException(\n                            String.format(\n                                    \"Output does not confirm to the schema.  errors: %s\", error));\n                }\n            }\n            // llmResponse.setResult(map);\n            return map;\n\n        } catch (JsonProcessingException e) {\n            if (chatCompletion.isJsonOutput()) {\n                log.error(\n                        \"error converting to json, response: {}, error: {}\",\n                        responseText,\n                        e.getMessage(),\n                        e);\n                Map<String, Object> outputErrors =\n                        Map.of(\"error\", e.getMessage(), \"response\", responseText);\n                throw new RuntimeException(objectMapper.writeValueAsString(outputErrors));\n            }\n            return responseText;\n        }\n    }\n\n    private String validateJsonSchema(final SchemaDef schema, Map<String, Object> data) {\n        try {\n            // Order in which we use the schema\n            // 1. If there is data -- inline schema def, we use that\n            // 2. Else use name + version to lookup\n            // 3. externalRef if present, in future we will use it -- currently not supported\n            String schemaContent = objectMapper.writeValueAsString(schema.getData());\n            if (schemaContent == null) {\n                return null;\n            }\n\n            Set<ValidationMessage> validationMessages =\n                    jsonSchemaValidator.validate(schemaContent, data);","sourceCodeStart":299,"sourceCodeEnd":335,"githubUrl":"https://github.com/conductor-oss/conductor/blob/cf7c3e4a8adfb158be778ab1ec525323c363cd3a/ai/src/main/java/org/conductoross/conductor/ai/LLMHelper.java#L299-L335","documentation":"Thrown by LLMHelper.tryToConvertToJSON() when the LLM response text cannot be parsed as JSON (JsonProcessingException) and isJsonOutput() is true. The exception carries a JSON string with the parse error message and the raw response text that failed to parse.","triggerScenarios":"The LLM is asked for JSON output (isJsonOutput true) but returns text that is not valid JSON — e.g. natural language with embedded JSON fragments, markdown without code fences, or truncated JSON. objectMapper.readValue() throws JsonProcessingException.","commonSituations":"The model wrapped JSON in explanatory text (e.g. 'Here is the result: {...}'). The response was truncated due to maxTokens limit, cutting off the JSON mid-string. The model returned a code block with unexpected fence formatting. The model returned prose instead of JSON despite instructions.","solutions":["Inspect the 'response' field in the thrown JSON payload to see the raw text the model returned","Increase maxTokens to prevent truncation of long JSON responses","Strengthen the prompt with explicit instructions like 'Respond ONLY with valid JSON, no markdown, no explanation'","Lower temperature to reduce non-deterministic formatting","If using a provider that supports response_format json_object, enable it"],"exampleFix":"// before: prompt says 'Return a summary'\n// after: prompt says 'Return ONLY valid JSON with no markdown fences, e.g. {\"summary\": \"...\"}'","handlingStrategy":"try-catch","validationCode":"// Before the LLM call, ensure JSON output instructions are clear\nif (chatCompletion.isJsonOutput()) {\n    String prompt = chatCompletion.getPrompt();\n    if (prompt != null && !prompt.toLowerCase().contains(\"json\")) {\n        log.warn(\"isJsonOutput is true but prompt does not mention JSON\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    LLMResponse response = llmHelper.chatComplete(task, llm, chatCompletion, location, logger);\n} catch (RuntimeException e) {\n    // Check if it's the JSON parse error with embedded payload\n    if (e.getMessage().startsWith(\"{\") && e.getMessage().contains(\"\\\"error\\\"\")) {\n        Map<String, Object> payload = objectMapper.readValue(e.getMessage(), Map.class);\n        log.warn(\"LLM returned non-JSON when JSON expected: raw={}\", payload.get(\"response\"));\n        // Optionally: re-prompt with stricter instructions or use a fallback parser\n    }\n    throw e;\n}","preventionTips":["Always include explicit 'respond ONLY with valid JSON' in the prompt when isJsonOutput is true","Set maxTokens high enough to avoid truncation of JSON responses","Use structured output / function calling features when the provider supports them","Test with the specific model being used — some models are better at JSON than others"],"tags":["ai","llm","json-parsing","json-output"],"backgroundTag":null,"analyzedSha":"cf7c3e4a8adfb158be778ab1ec525323c363cd3a","analyzedAt":"2026-08-14T03:33:19.897Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}