koala73/worldmonitor · warning · RpcValidationError
Could not resolve ${JSON.stringify(echoCountryInput(raw))} t
Error message
Could not resolve ${JSON.stringify(echoCountryInput(raw))} to a country. Pass an ISO 3166-1 alpha-2 code (e.g. "IQ"), an alpha-3 code ("IRQ"), or an English country name ("Iraq"). What it means
requireCountryCode validates MCP tool arguments against resolveCountryCode, which accepts ISO 3166-1 alpha-2, alpha-3, or English country names. If the input cannot be resolved, it throws an RpcValidationError whose description embeds the echoed (sanitized) input plus the COUNTRY_ARG_HINT, telling the caller exactly which formats are accepted.
Solutions
- Send a valid ISO 3166-1 alpha-2 code (e.g. "IQ") — the most reliable form
- Or send an alpha-3 code ("IRQ") or the exact English country name ("Iraq")
- Trim/canonicalize the value client-side before sending
- Check the error description: it echoes the offending input so you can see what actually arrived (encoding/quoting bugs show up here)
Example fix
// before
callTool('get-country-brief', { country_code: 'UK' }); // RpcValidationError
// after
callTool('get-country-brief', { country_code: 'GB' }); // resolves Defensive patterns
Strategy: validation
Validate before calling
const ISO2 = new Set(['IQ','GB','US']); // or full ISO list
function looksLikeCountryArg(v) { return typeof v === 'string' && /^[A-Za-z]{2,3}$/.test(v.trim()) || typeof v === 'string' && v.trim().length > 3; } Type guard
function isPlausibleCountryCode(v) { return typeof v === 'string' && v.trim().length >= 2 && v.trim().length <= 56; } Try / catch
try { return await tool.call(params); } catch (e) { if (e instanceof RpcValidationError) return { error: 'invalid_country', hint: e.violations[0]?.description }; throw e; } Prevention
- Canonicalize country inputs (trim, uppercase for alpha-2) before sending
- Prefer alpha-2 codes over names in programmatic clients
- Constrain LLM tool schemas to a 2-letter pattern for country_code
- Check the echoed input in the error description when debugging
When it happens
Trigger: Calling any MCP tool that funnels country arguments through requireCountryCode (via resolveCountryFilter/countryCode/code) with an unrecognized value: full ISO alpha-2 is expected, but things like 'uk', lowercase full names with typos, numeric codes, empty-ish strings that fail normalization, or localized names will not resolve.
Common situations: LLM tool callers emitting 'UK' style or full locale names ('United Kingdom of Great Britain...'); clients sending numeric ISO 3166-1 numeric codes; older integrations sending alpha-2 with whitespace/newlines that survive trim but fail matching.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Could not resolve ${JSON.stringify(echoCountryInput(raw))} t
- country must be an ISO 3166-1 alpha-2 country code, e.g. "UA
- must be an ISO 3166-1 alpha-2 country code.
- No focal-point coverage for ${countryCode}: that country is
- Invalid country
AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15).
Data as JSON: /api/errors/94d6b3fe8ff1c7cb.
Report an issue: GitHub.
Appendix: source
Thrown at api/mcp/_country-args.ts:26
// Never stringify a non-string. `String(x)` runs the value's own toString /
// valueOf, and `{"toString":"x"}` is legal JSON a caller can send: the
// shadowed, non-callable toString makes String() throw
// `TypeError: Cannot convert object to primitive value`. That turns this
// guard — whose whole job is to produce a clean 400 — into a 500. Describing
// the type is also more useful to the caller than `[object Object]`.
const text = typeof raw === 'string' ? raw.trim() : `<non-string ${typeof raw}>`;
return text.length > MAX_ECHOED_COUNTRY_INPUT
? `${text.slice(0, MAX_ECHOED_COUNTRY_INPUT)}…`
: text;
}
export const COUNTRY_ARG_HINT =
'Pass an ISO 3166-1 alpha-2 code (e.g. "IQ"), an alpha-3 code ("IRQ"), or an English country name ("Iraq").';
export function requireCountryCode(raw: unknown, operation: string, field = 'country_code'): string {
const resolved = resolveCountryCode(raw);
if (resolved) return resolved;
throw new RpcValidationError(operation, [{
field,
description: `Could not resolve ${JSON.stringify(echoCountryInput(raw))} to a country. ${COUNTRY_ARG_HINT}`,
}]);
}
/** Omitted optional filters retain the unfiltered result; invalid entries do not. */
export function resolveCountryFilter(raw: unknown, field: string): string[] {
if (raw == null || (typeof raw === 'string' && !raw.trim())) return [];
const values = Array.isArray(raw) ? raw : [raw];
return values.map((value) => requireCountryCode(value, 'country-filter', field).toLowerCase());
}
View on GitHub (pinned to 7d06c8633d)