koala73/worldmonitor · error · SafeWebMcpError
Dashboard tab list exceeded the safe output limit.
Error message
Dashboard tab list exceeded the safe output limit.
What it means
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.
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.
Example fix
// before
const { tabs } = await tools.call('list_dashboard_tabs', { limit: 1000 });
// after
const { tabs } = await tools.call('list_dashboard_tabs', { limit: 20, cursor });
// and keep tab names short when calling create/rename_dashboard_tab Defensive patterns
Strategy: validation
Validate before calling
function validTabListArgs(args) {
return (args.limit === undefined || (Number.isInteger(args.limit) && args.limit > 0))
&& (args.cursor === undefined || typeof args.cursor === 'string');
} Try / catch
try {
return await tools.call('list_dashboard_tabs', { limit: 20, cursor });
} catch (e) {
if (e.message.includes('tab list exceeded')) {
return tools.call('list_dashboard_tabs', { limit: 1, cursor });
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Dashboard panel catalog exceeded the safe output limit.
- Dashboard tab result exceeded the safe output limit.
- Dashboard navigation result exceeded the safe output limit.
- Airport delay page_size must be 0
- app_destroyed
AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-09-01).
Data as JSON: /api/errors/183777c264db3727.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/webmcp.ts:1536
? result.actionType
: 'move';
const status = result.status === 'applied' || result.status === 'denied' || result.status === 'invalid'
? result.status
: 'denied';
const ok = result.ok === true && status === 'applied';
const reason = result.reason && PANEL_LAYOUT_DENIAL_REASON_SET.has(result.reason)
? result.reason
: undefined;
const region = result.region === 'sidebar' || result.region === 'bottom'
? result.region
: undefined;
return {
ok,
status: ok ? 'applied' : status === 'invalid' ? 'invalid' : 'denied',
actionType,
...(result.panelId !== undefined
? { panelId: boundedText(result.panelId, PANEL_LAYOUT_ID_MAX_CHARS) }
: {}),
...(region ? { region } : {}),
...(typeof result.index === 'number' ? { index: Math.max(0, Math.floor(result.index)) } : {}),
...(typeof result.requestedCollapsed === 'boolean'
? { requestedCollapsed: result.requestedCollapsed }
: {}),
...(typeof result.effectiveCollapsed === 'boolean'
? { effectiveCollapsed: result.effectiveCollapsed }
: {}),
...(typeof result.requestedFullscreen === 'boolean'
? { requestedFullscreen: result.requestedFullscreen }
: {}),
...(typeof result.effectiveFullscreen === 'boolean'
? { effectiveFullscreen: result.effectiveFullscreen }
: {}),
...(ok ? { changed: result.changed === true } : { changed: false }),
...(result.unchanged === true ? { unchanged: true } : {}),
...(typeof result.persisted === 'boolean' ? { persisted: result.persisted } : {}),
...(!ok && reason ? { reason } : {}),View on GitHub (pinned to e586b8b4b8)