koala73/worldmonitor · error · SafeWebMcpError
Dashboard navigation result exceeded the safe output limit.
Error message
Dashboard navigation result exceeded the safe output limit.
What it means
boundDashboardNavigationResult composes a navigation envelope plus a context snapshot whose size is pre-budgeted (contextBudget = NAVIGATION_MAX_OUTPUT_CHARS - envelopeChars + 2), then does a final check against NAVIGATION_MAX_OUTPUT_CHARS. If the final serialized navigation result (e.g. from switch_monitor or focus_country) still exceeds the navigation output budget it throws this SafeWebMcpError. It is the last-resort guard for navigation payloads.
Solutions
- Retry the navigation — if a transient field inflated the envelope it may pass on a second call.
- Update WorldMonitor so tool bounder and dashboard payload shapes are from the same version.
- Reduce navigation input surface (e.g. target a monitor/country without huge metadata) to confirm the trigger.
- Report a bug with the tool name — the envelope should be structurally bounded, not able to exceed the budget.
Example fix
// before
await tools.call('switch_monitor', { monitor: someUnvalidatedInput });
// after
const monitors = await tools.call('get_dashboard_context', {});
const valid = monitors.monitors.some((m) => m.id === target);
if (valid) await tools.call('switch_monitor', { monitor: target }); Defensive patterns
Strategy: try-catch
Validate before calling
async function monitorExists(tools, monitor) {
const ctx = await tools.call('get_dashboard_context', {});
return Array.isArray(ctx.monitors) && ctx.monitors.some((m) => m.id === monitor);
} Try / catch
try {
return await tools.call('switch_monitor', { monitor });
} catch (e) {
if (e.message.includes('navigation result exceeded')) {
console.error('oversized navigation result for', monitor);
// fall back to a context refresh instead of the full navigation payload
return tools.call('get_dashboard_context', {});
}
throw e;
} Prevention
- Validate target monitor/country ids against get_dashboard_context before navigating.
- Keep tool and app versions aligned so envelope shapes stay bounded.
- Avoid navigating to targets known to carry huge metadata until trimmed.
- Treat repeated occurrences as a regression to report upstream.
When it happens
Trigger: A navigation tool call (switch_monitor, focus_country, applyDashboardAction-backed tools) where the envelope itself is so large that even after shrinking the context to zero the total exceeds NAVIGATION_MAX_OUTPUT_CHARS.
Common situations: A dashboard version adding large fields to the navigation envelope; monitors/countries with pathological metadata inflating envelope fields; version mismatch between tool bounder and app payload shape.
Related errors
- Dashboard panel catalog exceeded the safe output limit.
- Dashboard tab list exceeded the safe output limit.
- Dashboard tab result exceeded the safe output limit.
- app_destroyed
- app_destroyed
AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-09-01).
Data as JSON: /api/errors/b01dd361c162354e.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/webmcp.ts:1611
'list',
'tab_not_found',
'That dashboard tab cursor is no longer available.',
));
}
}
const buildPage = (
pageTabs: typeof tabs,
nextCursor: string | undefined,
): DashboardTabListSnapshot => ({
activeTabId,
tabs: pageTabs,
tabCount,
tabsTruncated: nextCursor !== undefined || snapshot.tabsTruncated === true,
canCreate,
cap,
...(createBlockReason ? { createBlockReason } : {}),
...(nextCursor ? { nextCursor: boundedText(nextCursor, 64) } : {}),
});
const remaining = tabs.slice(startIndex);
const page: typeof tabs = [];
for (let index = 0; index < remaining.length; index += 1) {
const tab = remaining[index];
if (!tab) continue;
const candidate = [...page, tab];
const following = remaining[index + 1];
if (JSON.stringify(buildPage(candidate, following?.id)).length > TARGET_OUTPUT_CHARS) {
break;
}
page.push(tab);
}
if (page.length === 0 && remaining[0]) page.push(remaining[0]);
const consumed = startIndex + page.length;
const nextCursor = consumed < tabs.length ? tabs[consumed]?.id : undefined;View on GitHub (pinned to e586b8b4b8)