{"record":{"id":"7458005366fc35a1","repo":"NousResearch/hermes-agent","slug":"session-transcript-exceeds-the-desktop-safe-load-l","errorCode":null,"errorMessage":"Session transcript exceeds the Desktop safe-load limit; use the Web Dashboard export for this session.","messagePattern":"Session transcript exceeds the Desktop safe-load limit; use the Web Dashboard export for this session\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/desktop/src/hermes.ts","lineNumber":737,"sourceCode":"  const messages: SessionMessage[] = []\n  const pageSize = 500\n  const maxJsonChars = options.maxJsonChars ?? 32_000_000\n  let jsonChars = 0\n  let offset = 0\n  let resolvedSessionId = id\n\n  while (true) {\n    const page = await getSessionMessages(id, profile, {\n      limit: pageSize,\n      offset,\n      order: 'oldest'\n    })\n\n    resolvedSessionId = page.session_id\n    jsonChars += (JSON.stringify(page.messages) ?? '').length\n\n    if (jsonChars > maxJsonChars) {\n      throw new Error(\n        'Session transcript exceeds the Desktop safe-load limit; use the Web Dashboard export for this session.'\n      )\n    }\n\n    messages.push(...page.messages)\n\n    // Legacy backends ignore pagination and return the full transcript.\n    if (!page.pagination || page.messages.length === 0 || page.messages.length < page.pagination.limit) {\n      break\n    }\n\n    offset += page.messages.length\n  }\n\n  return { session_id: resolvedSessionId, messages }\n}\n\nexport function deleteSession(id: string, profile?: string | null): Promise<{ ok: boolean }> {","sourceCodeStart":719,"sourceCodeEnd":755,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/src/hermes.ts#L719-L755","documentation":"Thrown by getAllSessionMessages() in apps/desktop/src/hermes.ts:737 when the accumulated JSON size of a session's transcript (paged at 500 messages, order 'oldest') exceeds maxJsonChars (default 32,000,000 characters). This is a deliberate protective cap: loading an unbounded transcript into the renderer would exhaust memory and freeze the app. The error tells the user to use the Web Dashboard's export for that session instead.","triggerScenarios":"Opening a session whose cumulative messages JSON exceeds 32 MB (measured with JSON.stringify per page); calling getAllSessionMessages with many pages until the counter passes the cap; calling with a custom smaller maxJsonChars option.","commonSituations":"Long-running agent sessions with huge tool outputs or base64 attachments; sessions shared across CLI/gateway surfaces that grew for weeks; importing old session databases; a user clicking a giant pinned session in the desktop transcript view.","solutions":["For that session, use the Web Dashboard export instead of the desktop full-transcript load.","Load incrementally: call getSessionMessages(page) with limit/offset and render a windowed list rather than getAllSessionMessages.","If you must load more and accept the memory risk, pass a larger options.maxJsonChars explicitly.","Trim the session (delete bulky old messages / start a new session) if desktop full-history viewing is a hard requirement."],"exampleFix":"// before\nconst all = await getAllSessionMessages(sessionId) // throws past 32 MB\n\n// after — windowed paging\nconst first = await getSessionMessages(sessionId, profile, { limit: 500, offset: 0, order: 'oldest' })\n// or explicit cap bump when the caller accepts the cost:\nconst all = await getAllSessionMessages(sessionId, profile, { maxJsonChars: 64_000_000 })","handlingStrategy":"try-catch","validationCode":"const SOFT_LIMIT = 32_000_000\n// pre-check via a lightweight estimate: fetch only the latest page first\nconst latest = await getLatestSessionMessages(id, profile)\n// if backend reports totals, compare before attempting the full walk","typeGuard":null,"tryCatchPattern":"try {\n  const all = await getAllSessionMessages(id, profile)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('safe-load limit')) {\n    // route the user to the Web Dashboard export; do NOT retry with a huge cap blindly\n    offerDashboardExport(id)\n  } else throw e\n}","preventionTips":["Prefer paged/windowed rendering via getSessionMessages over getAllSessionMessages","Treat the 32 MB default as a memory guard, not a bug","Only raise maxJsonChars deliberately for a known session on capable hardware","For archival needs, use the dashboard export instead of loading into the renderer"],"tags":["desktop","sessions","transcript","memory","limits"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}