{"record":{"id":"cda70d3b4cd04ffd","repo":"eyaltoledano/claude-task-master","slug":"error-saving-research-to-task-subtask-saveerror","errorCode":null,"errorMessage":"Error saving research to task/subtask: ${saveError.message}","messagePattern":"Error saving research to task/subtask: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"mcp-server/src/core/direct-functions/research.js","lineNumber":217,"sourceCode":"\t\t\t\t\t\ttaskIdNum,\n\t\t\t\t\t\tresearchContent,\n\t\t\t\t\t\tfalse, // useResearch = false for simple append\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tsession,\n\t\t\t\t\t\t\tmcpLog,\n\t\t\t\t\t\t\tcommandName: 'research-save',\n\t\t\t\t\t\t\toutputType: 'mcp',\n\t\t\t\t\t\t\tprojectRoot,\n\t\t\t\t\t\t\ttag\n\t\t\t\t\t\t},\n\t\t\t\t\t\t'json',\n\t\t\t\t\t\ttrue // appendMode = true\n\t\t\t\t\t);\n\n\t\t\t\t\tlog.info(`Research saved to task ${saveTo}`);\n\t\t\t\t}\n\t\t\t} catch (saveError) {\n\t\t\t\tlog.warn(`Error saving research to task/subtask: ${saveError.message}`);\n\t\t\t}\n\t\t}\n\n\t\t// Restore normal logging\n\t\tdisableSilentMode();\n\n\t\treturn {\n\t\t\tsuccess: true,\n\t\t\tdata: {\n\t\t\t\tquery: result.query,\n\t\t\t\tresult: result.result,\n\t\t\t\tcontextSize: result.contextSize,\n\t\t\t\tcontextTokens: result.contextTokens,\n\t\t\t\ttokenBreakdown: result.tokenBreakdown,\n\t\t\t\tsystemPromptTokens: result.systemPromptTokens,\n\t\t\t\tuserPromptTokens: result.userPromptTokens,\n\t\t\t\ttotalInputTokens: result.totalInputTokens,\n\t\t\t\tdetailLevel: result.detailLevel,","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/eyaltoledano/claude-task-master/blob/c0c98d367c55296bfe69e65680625b6db437af02/mcp-server/src/core/direct-functions/research.js#L199-L235","documentation":"researchDirect attempted to append the generated research output to a task or subtask (via --save-to) and the save call threw. The tool deliberately downgrades this to a warning so the research result is still returned to the caller even though it was not persisted to the task's details. It indicates the research succeeded but the persistence step failed.","triggerScenarios":"Calling the research tool with saveTo set to a task/subtask ID that does not exist, a tasks.json that is unwritable or missing, a cross-tag ID that fails resolution, or any exception thrown by the underlying save logic (e.g. JSON parse failure of tasks.json).","commonSituations":"Typo'd or stale task ID passed to saveTo; tasks.json deleted or corrupted mid-session; file permissions problem after moving the project; subtask ID like '5.2' that no longer exists after restructuring.","solutions":["Verify the saveTo ID exists (task-master list / show <id>) and correct it.","Check tasks.json exists, is valid JSON, and is writable in the project root.","Re-run the research command; the research text is in the tool response, so paste it manually into the task if saving keeps failing.","Inspect the full saveError via log output to identify the underlying cause (permissions, path, JSON)."],"exampleFix":"// before\nsaveTo = \"12.3\" // subtask deleted earlier\n// after\nsaveTo = \"12\" // or an existing subtask ID verified via task-master show","handlingStrategy":"try-catch","validationCode":"const exists = await tmCore.tasks.get(saveTo).catch(() => null);\nif (!exists) throw new Error(`Cannot save research: task '${saveTo}' not found`);\nif (!fs.existsSync(tasksJsonPath)) throw new Error('tasks.json missing from project root');","typeGuard":"function isTaskId(value) {\n  return typeof value === 'string' && /^([A-Z]+-)?\\d+(\\.\\d+)?$/.test(value.trim());\n}","tryCatchPattern":"try {\n  await tmCore.tasks.saveResearchToTask(saveTo, researchText);\n} catch (err) {\n  log.warn(`Research not saved to '${saveTo}': ${err.message} — keeping result in response only`, { cause: err.message });\n}","preventionTips":["Resolve and validate the saveTo ID (task-master show <id>) before running research.","Ensure tasks.json exists and is writable in the resolved project root.","Treat the research response text as the source of truth and back it up manually when saving is optional."],"tags":["mcp","file-io","task-persistence","non-fatal"],"backgroundTag":"task-save-failed","analyzedSha":"c0c98d367c55296bfe69e65680625b6db437af02","analyzedAt":"2026-08-29T02:56:26.071Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}