{"record":{"id":"183777c264db3727","repo":"koala73/worldmonitor","slug":"dashboard-tab-list-exceeded-the-safe-output-limit","errorCode":null,"errorMessage":"Dashboard tab list exceeded the safe output limit.","messagePattern":"Dashboard tab list exceeded the safe output limit\\.","errorType":"error_code","errorClass":"SafeWebMcpError","httpStatus":null,"severity":"error","filePath":"src/services/webmcp.ts","lineNumber":1536,"sourceCode":"    ? result.actionType\n    : 'move';\n  const status = result.status === 'applied' || result.status === 'denied' || result.status === 'invalid'\n    ? result.status\n    : 'denied';\n  const ok = result.ok === true && status === 'applied';\n  const reason = result.reason && PANEL_LAYOUT_DENIAL_REASON_SET.has(result.reason)\n    ? result.reason\n    : undefined;\n  const region = result.region === 'sidebar' || result.region === 'bottom'\n    ? result.region\n    : undefined;\n  return {\n    ok,\n    status: ok ? 'applied' : status === 'invalid' ? 'invalid' : 'denied',\n    actionType,\n    ...(result.panelId !== undefined\n      ? { panelId: boundedText(result.panelId, PANEL_LAYOUT_ID_MAX_CHARS) }\n      : {}),\n    ...(region ? { region } : {}),\n    ...(typeof result.index === 'number' ? { index: Math.max(0, Math.floor(result.index)) } : {}),\n    ...(typeof result.requestedCollapsed === 'boolean'\n      ? { requestedCollapsed: result.requestedCollapsed }\n      : {}),\n    ...(typeof result.effectiveCollapsed === 'boolean'\n      ? { effectiveCollapsed: result.effectiveCollapsed }\n      : {}),\n    ...(typeof result.requestedFullscreen === 'boolean'\n      ? { requestedFullscreen: result.requestedFullscreen }\n      : {}),\n    ...(typeof result.effectiveFullscreen === 'boolean'\n      ? { effectiveFullscreen: result.effectiveFullscreen }\n      : {}),\n    ...(ok ? { changed: result.changed === true } : { changed: false }),\n    ...(result.unchanged === true ? { unchanged: true } : {}),\n    ...(typeof result.persisted === 'boolean' ? { persisted: result.persisted } : {}),\n    ...(!ok && reason ? { reason } : {}),","sourceCodeStart":1518,"sourceCodeEnd":1554,"githubUrl":"https://github.com/koala73/worldmonitor/blob/e586b8b4b80f595aa7ece295eec10d76f2921240/src/services/webmcp.ts#L1518-L1554","documentation":"The dashboard tab list bounder builds a page of tabs with a nextCursor and validates the serialized page against MAX_OUTPUT_CHARS. If a single page of the tab list still cannot fit within the safe output budget, it throws this SafeWebMcpError instead of returning an oversized result. It guarantees list_dashboard_tabs responses stay within the WebMCP channel limits.","triggerScenarios":"Calling list_dashboard_tabs when even one page of tabs (including the forced first-entry fallback) serializes beyond MAX_OUTPUT_CHARS — e.g. tabs with extremely long names/urls/state blobs.","commonSituations":"Users with many tabs where each tab object carries verbose metadata; tabs with very long user-chosen names or embedded state; a corrupted/overgrown persisted tab store.","solutions":["Rename or clean up tabs with excessively long names; trim persisted tab state.","Use cursor-based pagination and request the list in multiple calls rather than one large page.","Reset the tab store if it has grown pathologically (export needed tabs, clear, recreate).","If a single tab alone cannot fit the budget, report a bug — the bounder should truncate per-tab fields."],"exampleFix":"// before\nconst { tabs } = await tools.call('list_dashboard_tabs', { limit: 1000 });\n// after\nconst { tabs } = await tools.call('list_dashboard_tabs', { limit: 20, cursor });\n// and keep tab names short when calling create/rename_dashboard_tab","handlingStrategy":"validation","validationCode":"function validTabListArgs(args) {\n  return (args.limit === undefined || (Number.isInteger(args.limit) && args.limit > 0))\n    && (args.cursor === undefined || typeof args.cursor === 'string');\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await tools.call('list_dashboard_tabs', { limit: 20, cursor });\n} catch (e) {\n  if (e.message.includes('tab list exceeded')) {\n    return tools.call('list_dashboard_tabs', { limit: 1, cursor });\n  }\n  throw e;\n}","preventionTips":["Keep tab names short when creating/renaming tabs.","Prune stale tabs so the store stays small.","Paginate with cursor instead of requesting all tabs at once.","Watch for tabs whose persisted state blobs grow unboundedly."],"tags":["webmcp","output-budget","tabs","pagination"],"backgroundTag":"response-size-limit-exceeded","analyzedSha":"e586b8b4b80f595aa7ece295eec10d76f2921240","analyzedAt":"2026-09-01T10:32:37.851Z","contentChangedAt":"2026-09-01T10:32:37.851Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}