koala73/worldmonitor · error · SafeWebMcpError

iso2 must be an ISO 3166-1 alpha-2 code, such as "DE" or…

Error message

iso2 must be an ISO 3166-1 alpha-2 code, such as "DE" or "IR".

What it means

Validation error text for the open_country_brief WebMCP tool's iso2 argument. The guard fires when iso2 is not a two-letter uppercase ISO 3166-1 alpha-2 country code (lowercase, three letters, digits, or wrong casing), as enforced by the ^[A-Z]{2}$ pattern; examples like DE or IR show the expected format. Opening the brief can consume daily briefing quota; use focus_country to only pan the map.

Solutions

  1. Pass a valid ISO 3166-1 alpha-2 country code: exactly two uppercase letters (e.g. "DE", "IR", "US"). Uppercase the input and trim whitespace before validating.
  2. Validate against /^[A-Z]{2}$/ plus, if strictness is required, a known-code list; reject early with this message and the received value so the caller can self-correct.
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at src/services/webmcp.ts:556 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-08-27). Data as JSON: /api/errors/97b964998f533c0f. Report an issue: GitHub.

Appendix: source

Thrown at src/services/webmcp.ts:1712

    ...(result.tab ? { tab: boundedText(result.tab, 32) } : {}),
    ...(result.reason ? { reason: boundedText(result.reason, 64) } : {}),
    message: boundedText(result.message, 240),
    context: {},
  };
  const envelopeChars = JSON.stringify(envelope).length;
  // `"context":{}` is already in the envelope; the empty object is 2 chars.
  const contextBudget = Math.max(0, NAVIGATION_MAX_OUTPUT_CHARS - envelopeChars + 2);
  const bounded = {
    ...envelope,
    context: boundDashboardContext(result.context ?? EMPTY_NAV_CONTEXT, contextBudget),
  };
  if (JSON.stringify(bounded).length > NAVIGATION_MAX_OUTPUT_CHARS) {
    throw new SafeWebMcpError('Dashboard navigation result exceeded the safe output limit.');
  }
  return bounded;
}

async function applyDashboardTabAction(
  action: DashboardTabAction,
  app: WebMcpAppBindings,
  options?: WebMcpExecutionOptions,
): Promise<DashboardTabActionResult> {
  const result = await app.applyDashboardTabAction(action, options);
  return isDashboardTabListSnapshot(result)
    ? boundDashboardTabList(result, action.type === 'list' ? action.cursor : undefined)
    : boundDashboardTabMutation(result);
}

function hasOnlyOwnKeys(
  value: Record<string, unknown>,
  allowedKeys: readonly string[],
): boolean {
  const allowed = new Set(allowedKeys);
  return Object.keys(value).every((key) => allowed.has(key));
}

View on GitHub (pinned to e586b8b4b8)