{"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":1528,"sourceCode":"  const remaining = tabs.slice(startIndex);\n  const page: typeof tabs = [];\n  for (let index = 0; index < remaining.length; index += 1) {\n    const tab = remaining[index];\n    if (!tab) continue;\n    const candidate = [...page, tab];\n    const following = remaining[index + 1];\n    if (JSON.stringify(buildPage(candidate, following?.id)).length > TARGET_OUTPUT_CHARS) {\n      break;\n    }\n    page.push(tab);\n  }\n  if (page.length === 0 && remaining[0]) page.push(remaining[0]);\n\n  const consumed = startIndex + page.length;\n  const nextCursor = consumed < tabs.length ? tabs[consumed]?.id : undefined;\n  const result = buildPage(page, nextCursor);\n  if (JSON.stringify(result).length > MAX_OUTPUT_CHARS) {\n    throw new SafeWebMcpError('Dashboard tab list exceeded the safe output limit.');\n  }\n  return result;\n}\n\nfunction boundDashboardTabMutation(result: DashboardTabMutationResult): DashboardTabMutationResult {\n  const bounded: DashboardTabMutationResult = {\n    ok: result.ok === true,\n    status: result.status,\n    actionType: result.actionType,\n    message: boundedText(result.message, 240),\n    ...(result.reason ? { reason: boundedText(result.reason, 64) as DashboardTabMutationResult['reason'] } : {}),\n    ...(result.tabId ? { tabId: boundedText(result.tabId, 64) } : {}),\n    ...(result.name ? { name: boundedText(result.name, DASHBOARD_TAB_NAME_MAX_LENGTH) } : {}),\n    ...(result.activeTabId ? { activeTabId: boundedText(result.activeTabId, 64) } : {}),\n    ...(result.unchanged === true ? { unchanged: true } : {}),\n    ...(result.alreadyExisted === true ? { alreadyExisted: true } : {}),\n    ...(typeof result.persisted === 'boolean' ? { persisted: result.persisted } : {}),\n    ...(typeof result.tabCount === 'number' ? { tabCount: Math.max(0, Math.floor(result.tabCount)) } : {}),","sourceCodeStart":1510,"sourceCodeEnd":1546,"githubUrl":"https://github.com/koala73/worldmonitor/blob/9361220cc013571781071f0206e4d80fd14b2f7f/src/services/webmcp.ts#L1510-L1546","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":"9361220cc013571781071f0206e4d80fd14b2f7f","analyzedAt":"2026-09-01T10:32:37.851Z","contentChangedAt":"2026-09-01T10:32:37.851Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}