{"record":{"id":"b01dd361c162354e","repo":"koala73/worldmonitor","slug":"dashboard-navigation-result-exceeded-the-safe-outp","errorCode":null,"errorMessage":"Dashboard navigation result exceeded the safe output limit.","messagePattern":"Dashboard navigation result exceeded the safe output limit\\.","errorType":"error_code","errorClass":"SafeWebMcpError","httpStatus":null,"severity":"error","filePath":"src/services/webmcp.ts","lineNumber":1611,"sourceCode":"        'list',\n        'tab_not_found',\n        'That dashboard tab cursor is no longer available.',\n      ));\n    }\n  }\n\n  const buildPage = (\n    pageTabs: typeof tabs,\n    nextCursor: string | undefined,\n  ): DashboardTabListSnapshot => ({\n    activeTabId,\n    tabs: pageTabs,\n    tabCount,\n    tabsTruncated: nextCursor !== undefined || snapshot.tabsTruncated === true,\n    canCreate,\n    cap,\n    ...(createBlockReason ? { createBlockReason } : {}),\n    ...(nextCursor ? { nextCursor: boundedText(nextCursor, 64) } : {}),\n  });\n\n  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;","sourceCodeStart":1593,"sourceCodeEnd":1629,"githubUrl":"https://github.com/koala73/worldmonitor/blob/e586b8b4b80f595aa7ece295eec10d76f2921240/src/services/webmcp.ts#L1593-L1629","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait tools.call('switch_monitor', { monitor: someUnvalidatedInput });\n// after\nconst monitors = await tools.call('get_dashboard_context', {});\nconst valid = monitors.monitors.some((m) => m.id === target);\nif (valid) await tools.call('switch_monitor', { monitor: target });","handlingStrategy":"try-catch","validationCode":"async function monitorExists(tools, monitor) {\n  const ctx = await tools.call('get_dashboard_context', {});\n  return Array.isArray(ctx.monitors) && ctx.monitors.some((m) => m.id === monitor);\n}","typeGuard":null,"tryCatchPattern":"try {\n  return await tools.call('switch_monitor', { monitor });\n} catch (e) {\n  if (e.message.includes('navigation result exceeded')) {\n    console.error('oversized navigation result for', monitor);\n    // fall back to a context refresh instead of the full navigation payload\n    return tools.call('get_dashboard_context', {});\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["webmcp","output-budget","navigation","context-snapshot"],"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"}