koala73/worldmonitor · error · SafeWebMcpError

Dashboard tab result exceeded the safe output limit.

Error message

Dashboard tab result exceeded the safe output limit.

What it means

boundDashboardTabMutation sanitizes a tab mutation result (create/rename/delete/select), coercing counts, capping lockReason to 32 chars, and then asserts the serialized result fits MAX_OUTPUT_CHARS. If it still exceeds the budget it throws this SafeWebMcpError. Mutation results are tiny by design, so hitting this indicates the result structurally ballooned beyond what the bounder can trim.

Source

Thrown at src/services/webmcp.ts:1552

  const bounded: DashboardTabMutationResult = {
    ok: result.ok === true,
    status: result.status,
    actionType: result.actionType,
    message: boundedText(result.message, 240),
    ...(result.reason ? { reason: boundedText(result.reason, 64) as DashboardTabMutationResult['reason'] } : {}),
    ...(result.tabId ? { tabId: boundedText(result.tabId, 64) } : {}),
    ...(result.name ? { name: boundedText(result.name, DASHBOARD_TAB_NAME_MAX_LENGTH) } : {}),
    ...(result.activeTabId ? { activeTabId: boundedText(result.activeTabId, 64) } : {}),
    ...(result.unchanged === true ? { unchanged: true } : {}),
    ...(result.alreadyExisted === true ? { alreadyExisted: true } : {}),
    ...(typeof result.persisted === 'boolean' ? { persisted: result.persisted } : {}),
    ...(typeof result.tabCount === 'number' ? { tabCount: Math.max(0, Math.floor(result.tabCount)) } : {}),
    ...(typeof result.canCreate === 'boolean' ? { canCreate: result.canCreate } : {}),
    ...(result.cap === null || typeof result.cap === 'number' ? { cap: result.cap } : {}),
    ...(result.lockReason ? { lockReason: boundedText(result.lockReason, 32) as DashboardTabMutationResult['lockReason'] } : {}),
  };
  if (JSON.stringify(bounded).length > MAX_OUTPUT_CHARS) {
    throw new SafeWebMcpError('Dashboard tab result exceeded the safe output limit.');
  }
  return bounded;
}

const EMPTY_NAV_CONTEXT: DashboardContextSnapshot = {
  variant: '',
  map: {
    view: '',
    center: null,
    zoom: 0,
    timeRange: '',
    enabledLayers: [],
  },
  panels: {
    mounted: [],
    enabled: [],
  },
};

View on GitHub (pinned to 9361220cc0)

Solutions

  1. Retry the mutation once; this is not expected in normal operation and may be transient state.
  2. Check whether you are on a dashboard version that added fields to DashboardTabMutationResult; upgrade or downgrade to a matched pair of tool/app versions.
  3. Shorten the tab name/id you are mutating to rule out oversize user input.
  4. Report a bug with the tool name and args — the bounder should always produce a sub-budget mutation result.

Example fix

// before
await tools.call('rename_dashboard_tab', { id, name: 'x'.repeat(5000) });
// after
await tools.call('rename_dashboard_tab', { id, name: name.slice(0, 64) });
Defensive patterns

Strategy: try-catch

Validate before calling

function validTabMutationArgs(args) {
  return typeof args.id === 'string' && args.id.length <= 128
    && (args.name === undefined || (typeof args.name === 'string' && args.name.length <= 64));
}

Try / catch

try {
  return await tools.call('rename_dashboard_tab', { id, name });
} catch (e) {
  if (e.message.includes('tab result exceeded')) {
    // unexpected: mutation results are tiny; log and retry once, then report
    console.error('oversized tab mutation result', { id, name: name.length });
    return tools.call('rename_dashboard_tab', { id, name: name.slice(0, 32) });
  }
  throw e;
}

Prevention

When it happens

Trigger: A create_dashboard_tab / rename_dashboard_tab / delete_dashboard_tab / select_dashboard_tab call whose bounded result object still serializes above MAX_OUTPUT_CHARS — practically only when the result carries oversized fields the bounder does not truncate.

Common situations: A dashboard version returning extra unbounded fields in the mutation result; extremely long tab ids or lockReason variants; a regression where the bounder's field whitelist stopped covering a new large field.

Related errors


AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-09-01). Data as JSON: /api/errors/be3ec1ba3523f81d. Report an issue: GitHub.