{"record":{"id":"a92f931bfaabff9f","repo":"eyaltoledano/claude-task-master","slug":"failed-to-parse-ai-response-as-json-error-messa","errorCode":null,"errorMessage":"Failed to parse AI response as JSON: ${error.message}","messagePattern":"Failed to parse AI response as JSON: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/utils/stream-parser.js","lineNumber":318,"sourceCode":"\t\t// Only add items we haven't already parsed\n\t\tconst itemsToAdd = fallbackItems.slice(\n\t\t\tthis.progressTracker.parsedItems.length\n\t\t);\n\t\tconst newItems = [];\n\n\t\tfor (const item of itemsToAdd) {\n\t\t\tif (this.config.itemValidator(item)) {\n\t\t\t\tnewItems.push(item);\n\t\t\t\tthis.progressTracker.addItem(item);\n\t\t\t}\n\t\t}\n\n\t\treturn newItems;\n\t}\n\n\thandleFallbackError(error) {\n\t\tif (this.progressTracker.parsedItems.length === 0) {\n\t\t\tthrow new Error(`Failed to parse AI response as JSON: ${error.message}`);\n\t\t}\n\t\t// If we have some items from streaming, continue with those\n\t}\n}\n\n/**\n * Buffer size validator\n */\nclass BufferSizeValidator {\n\tconstructor(maxSize) {\n\t\tthis.maxSize = maxSize;\n\t\tthis.currentSize = 0;\n\t}\n\n\tvalidateChunk(existingText, newChunk) {\n\t\tconst newSize = Buffer.byteLength(existingText + newChunk, 'utf8');\n\n\t\tif (newSize > this.maxSize) {","sourceCodeStart":300,"sourceCodeEnd":336,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/src/utils/stream-parser.js#L300-L336","documentation":"When JSON path extraction fails, the parser tries the fallbackItemExtractor; if that also throws, handleFallbackError decides whether to surface the failure. If no items were parsed from streaming at all, it throws 'Failed to parse AI response as JSON: <reason>'. This means the AI output contained no parseable JSON matching any jsonPath and no items were recovered.","triggerScenarios":"The model returned prose/markdown with no JSON; the response was truncated mid-JSON due to max tokens; jsonPath does not match the actual response shape (e.g. '$.items' but response nests under '$.data.items'); streaming produced zero items and then a JSON.parse error occurred during final parsing.","commonSituations":"Changing the prompt so the model stops emitting JSON; asking for output in a different shape than the configured jsonPaths; truncated responses from token limits; the stream erroring before any items were emitted so there is nothing to fall back on.","solutions":["Log/inspect error.message from the thrown error to see the underlying JSON.parse failure and the raw response.","Check jsonPaths matches the actual response structure (use the raw text to verify).","Add/adjust the system prompt to force valid JSON-only output, or parse a fenced ```json block in fallbackItemExtractor.","Increase max tokens or handle truncation so the JSON is not cut off mid-stream."],"exampleFix":"// before\nconst parser = new StreamParser({ jsonPaths: ['$.items'] });\n// after\nconst parser = new StreamParser({\n  jsonPaths: ['$.items', '$.data.items'], // cover actual response shapes\n  fallbackItemExtractor: (text) => {\n    const m = text.match(/```json\\n([\\s\\S]*?)```/);\n    return m ? JSON.parse(m[1]).items : [];\n  }\n});","handlingStrategy":"try-catch","validationCode":"function looksLikeJson(text) {\n  const t = text.trim();\n  return t.startsWith('{') || t.startsWith('[') || /```json/.test(t);\n}\n// check accumulated stream text before final parse; if !looksLikeJson(text), surface/prompt-retry early","typeGuard":null,"tryCatchPattern":"try {\n  const items = await parser.parseStream(stream);\n  return items;\n} catch (err) {\n  if (err.message.startsWith('Failed to parse AI response as JSON')) {\n    // no items recovered: retry with stricter JSON prompt or inspect raw text\n    logger.error('AI response not parseable', err.message);\n    return retryWithJsonOnlyPrompt();\n  }\n  throw err;\n}","preventionTips":["Enforce JSON-only output in the system prompt and validate with a quick pre-parse.","Configure jsonPaths to match the actual response nesting; test with real samples.","Raise max tokens / handle truncation so JSON is not cut off.","Provide a fallbackItemExtractor that can salvage fenced ```json blocks."],"tags":["json","parsing","streaming","ai-response"],"backgroundTag":"json-parse-failed","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}