{"record":{"id":"0934cde20095ac3f","repo":"CherryHQ/cherry-studio","slug":"failed-to-read-journal-at-journalpath-err-a","errorCode":null,"errorMessage":"Failed to read journal at ${journalPath}: ${(err as Error).message}","messagePattern":"Failed to read journal at (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/mcp/servers/agentMemory.ts","lineNumber":298,"sourceCode":"\n    const memoryDir = await this.assertMemoryDirectory()\n    const journalPath = await resolveFileCI(memoryDir, 'JOURNAL.jsonl')\n\n    let fileContent: string\n    try {\n      const handle = await open(journalPath, withNoFollow(constants.O_RDONLY))\n      try {\n        const fileStat = await handle.stat()\n        if (!fileStat.isFile()) throw new Error(`Agent journal must be a regular file: ${journalPath}`)\n        fileContent = await handle.readFile('utf-8')\n      } finally {\n        await handle.close()\n      }\n    } catch (err) {\n      if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n        return { content: [{ type: 'text' as const, text: 'No journal entries found.' }] }\n      }\n      throw new Error(`Failed to read journal at ${journalPath}: ${(err as Error).message}`)\n    }\n\n    const queryLower = query.toLowerCase()\n    const tagLower = tagFilter.toLowerCase()\n    const matches: JournalEntry[] = []\n\n    for (const line of fileContent.split('\\n')) {\n      if (!line.trim()) continue\n      let entry: JournalEntry\n      try {\n        entry = JSON.parse(line)\n      } catch {\n        logger.warn('Skipping corrupted journal line', { journalPath, line: line.substring(0, 100) })\n        continue\n      }\n      if (tagFilter && !entry.tags?.some((t) => t.toLowerCase() === tagLower)) continue\n      if (query && !entry.text.toLowerCase().includes(queryLower)) continue\n      matches.push(entry)","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/mcp/servers/agentMemory.ts#L280-L316","documentation":"In memorySearch(), any error from opening or reading the journal that is NOT ENOENT is re-thrown wrapped with context. ENOENT is treated as 'no journal yet' and returns a friendly message; all other failures (EACCES, EIO, ENOSPC, etc.) bubble up as this wrapped Error, which the outer CallToolRequest catch converts into an isError response.","triggerScenarios":"The journal exists but cannot be read: permission denied (EACCES), disk I/O error (EIO), path too long, or the file is locked by another process in a way that blocks the read.","commonSituations":"File permissions were changed after creation (chmod); the disk has bad sectors; antivirus or another process holds an exclusive lock; the userData directory was moved to read-only media.","solutions":["Check permissions on the journal file and parent directory: ls -la <agentDataPath>/memory/.","Ensure the Electron process has read access (same user that wrote it).","If the disk is failing, run filesystem checks and restore from backup."],"exampleFix":"# before: file owned by root after a bad migration\nls -la memory/JOURNAL.jsonl  # -rw------- root root\n\n# after: fix ownership to the app user\nchown $USER:$USER memory/JOURNAL.jsonl","handlingStrategy":"try-catch","validationCode":"import { access } from 'node:fs/promises'\nimport { constants } from 'node:fs'\n\nasync function isReadable(p: string): Promise<boolean> {\n  try {\n    await access(p, constants.R_OK)\n    return true\n  } catch {\n    return false\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await memorySearch(args)\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Failed to read journal')) {\n    logger.warn('Journal read failed', { error: err.message })\n    return { content: [{ type: 'text', text: 'Journal temporarily unavailable.' }] }\n  }\n  throw err\n}","preventionTips":["Ensure the Electron process owns its userData files and has read access.","Do not move userData to read-only media without updating permissions.","Surface the wrapped message to the user so they can fix permissions."],"tags":["filesystem","io-error","permissions","agent-memory"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}