{"record":{"id":"4a167399f0d2e2ff","repo":"eyaltoledano/claude-task-master","slug":"failed-to-parse-json-response-parseerror-messag","errorCode":null,"errorMessage":"Failed to parse JSON response: ${parseError.message}. Response: ${result.text.substring(0, 200)}...","messagePattern":"Failed to parse JSON response: (.+?)\\. Response: (.+?)\\.\\.\\.","errorType":"exception","errorClass":"MCPError","httpStatus":null,"severity":"error","filePath":"mcp-server/src/custom-sdk/language-model.js","lineNumber":150,"sourceCode":"\t\t\t\t\tincludeContext: 'thisServer'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttimeout: 240000 // 4 minutes timeout\n\t\t\t\t}\n\t\t\t);\n\n\t\t\t// Convert MCP response back to AI SDK format\n\t\t\tconst result = convertFromMCPFormat(response);\n\n\t\t\t// Extract JSON from the response text\n\t\t\tconst jsonText = extractJson(result.text);\n\n\t\t\t// Parse and validate JSON\n\t\t\tlet parsedObject;\n\t\t\ttry {\n\t\t\t\tparsedObject = JSON.parse(jsonText);\n\t\t\t} catch (parseError) {\n\t\t\t\tthrow new MCPError(\n\t\t\t\t\t`Failed to parse JSON response: ${parseError.message}. Response: ${result.text.substring(0, 200)}...`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Validate against schema\n\t\t\ttry {\n\t\t\t\tconst validatedObject = schema.parse(parsedObject);\n\n\t\t\t\treturn {\n\t\t\t\t\tobject: validatedObject,\n\t\t\t\t\tfinishReason: result.finishReason || 'stop',\n\t\t\t\t\tusage: {\n\t\t\t\t\t\tpromptTokens: result.usage?.inputTokens || 0,\n\t\t\t\t\t\tcompletionTokens: result.usage?.outputTokens || 0,\n\t\t\t\t\t\ttotalTokens:\n\t\t\t\t\t\t\t(result.usage?.inputTokens || 0) +\n\t\t\t\t\t\t\t(result.usage?.outputTokens || 0)\n\t\t\t\t\t},","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/mcp-server/src/custom-sdk/language-model.js#L132-L168","documentation":"doGenerateObject expects the model's text output to be JSON and calls JSON.parse on it; when parsing fails it wraps the syntax error in an MCPError that includes the parser message and the first 200 characters of the response for debugging. The model returned non-JSON text (prose, markdown fences, truncated output) instead of a JSON object.","triggerScenarios":"MCP sampling response text is not valid JSON: model added markdown code fences or commentary, output was truncated by maxTokens, or the prompt/jsonInstructions did not constrain the model to JSON.","commonSituations":"Small/weak models ignoring JSON instructions; large schemas cut off by token limits; responses wrapped in ```json fences; empty response text.","solutions":["Increase maxTokens / reduce schema size so the JSON is not truncated","Strengthen the prompt to demand raw JSON only (no fences/commentary), or strip code fences before parsing","Retry generation; if intermittent, consider a more capable model for structured output"],"exampleFix":"// before\nconst obj = JSON.parse(result.text);\n// after\nconst jsonText = result.text.replace(/^```(?:json)?\\n?|\\n?```$/g, '').trim();\nconst obj = JSON.parse(jsonText);","handlingStrategy":"try-catch","validationCode":"function isProbablyJson(text) {\n  if (typeof text !== 'string' || !text.trim().startsWith('{')) return false;\n  try { JSON.parse(text); return true; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try { obj = await model.doGenerateObject(opts); } catch (e) {\n  if (e.message.startsWith('Failed to parse JSON response')) {\n    // inspect e.message for the first 200 chars; increase maxTokens and retry\n  } else throw e;\n}","preventionTips":["Set maxTokens high enough for the full JSON payload","Prompt for raw JSON with no markdown fences or commentary","Prefer models known to follow structured-output instructions; validate response shape before use"],"tags":["mcp","ai-sdk","json","llm-output"],"backgroundTag":"invalid-json-response","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}