{"record":{"id":"54cd97472138f571","repo":"mastra-ai/mastra","slug":"failed-to-parse-working-memory-input-as-json-er","errorCode":null,"errorMessage":"Failed to parse working memory input as JSON: ${errorMessage}. Raw input: ${memoryInput.length > 500 ? memoryInput.slice(0, 500) + '...' : memoryInput}","messagePattern":"Failed to parse working memory input as JSON: (.+?)\\. Raw input: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/memory/src/tools/working-memory.ts","lineNumber":265,"sourceCode":"            // If existing data is not valid JSON, start fresh\n            existingData = null;\n          }\n        }\n\n        // Handle case where LLM passes empty object or no memory field\n        const memoryInput = workingMemoryInput.memory;\n        if (memoryInput === undefined || memoryInput === null) {\n          // No data to update - return existing data unchanged\n          return { success: true, message: 'No memory data provided, existing memory unchanged.' };\n        }\n\n        let newData: unknown;\n        if (typeof memoryInput === 'string') {\n          try {\n            newData = JSON.parse(memoryInput);\n          } catch (parseError) {\n            const errorMessage = parseError instanceof Error ? parseError.message : String(parseError);\n            throw new Error(\n              `Failed to parse working memory input as JSON: ${errorMessage}. ` +\n                `Raw input: ${memoryInput.length > 500 ? memoryInput.slice(0, 500) + '...' : memoryInput}`,\n            );\n          }\n        } else {\n          newData = memoryInput;\n        }\n\n        const mergedData = deepMergeWorkingMemory(existingData, newData as Record<string, unknown>);\n        workingMemory = JSON.stringify(mergedData);\n      } else {\n        // Template-based (Markdown): use existing replace semantics\n        const memoryInput = workingMemoryInput.memory;\n        workingMemory = typeof memoryInput === 'string' ? memoryInput : JSON.stringify(memoryInput);\n\n        // Validate that we're not replacing good data with an empty template\n        // This prevents accidental data loss when the LLM returns just the template\n        const existingRaw = await memory.getWorkingMemory({","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/tools/working-memory.ts#L247-L283","documentation":"In schema-based (merge-semantics) working memory, the model passed the memory field as a string that is not valid JSON, so it cannot be merged into the stored JSON document. Mastra wraps the underlying JSON.parse error and includes a truncated copy of the raw input (max 500 chars) to help debug what the LLM emitted.","triggerScenarios":"The LLM calls the update-working-memory tool with memory as a string containing Markdown, prose, trailing commas, single quotes, or comments instead of a JSON document, while working memory is configured with a JSON schema.","commonSituations":"Model ignores the 'pass data as JSON string' instruction and writes natural language; template/Markdown habits leaking into schema-mode memory; model emits code fences (```json ... ```) inside the string; malformed escaping of quotes in the JSON string.","solutions":["Strengthen the tool prompt/description so the model knows schema-mode memory must be valid JSON (the tool description already asks for merge-friendly JSON; make your schema fields obvious).","Parse/repair on your side by adding a memory processor or custom tool wrapper that strips code fences and retries the call.","Check the raw input in the error message for code fences or prose and adjust prompts accordingly.","Consider using template-based working memory (no schema) if you actually want Markdown replacement semantics instead of JSON merge."],"exampleFix":"// before (model output, fails)\nmemory: '{ name: \"Sam\", likes: pizza }'\n// after (valid JSON string)\nmemory: '{\"name\":\"Sam\",\"likes\":\"pizza\"}'","handlingStrategy":"validation","validationCode":"function isSerializableJson(value: string): boolean {\n  try { JSON.parse(value); return true; } catch { return false; }\n}\n// validate the tool input before accepting it\nif (typeof modelOutput.memory === 'string' && !isSerializableJson(modelOutput.memory)) {\n  // retry the model call with a stricter instruction\n}","typeGuard":"const isJsonString = (v: string): boolean => {\n  if (typeof v !== 'string') return false;\n  try { JSON.parse(v); return true; } catch { return false; }\n};","tryCatchPattern":"try {\n  await agent.generate(input, opts);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Failed to parse working memory input as JSON')) {\n    // inspect e.message for the raw input; retry with corrected prompt\n  }\n}","preventionTips":["Include 'pass valid JSON' examples in the agent instructions when using schema working memory.","Strip markdown code fences from model output via a processor before the tool runs.","Test the exact tool description against your model of choice; weaker models need more explicit JSON instructions.","Use template (Markdown) working memory if you prefer prose over JSON."],"tags":["memory","working-memory","json","llm-output","parsing"],"backgroundTag":"json-parse-error","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}