{"record":{"id":"4f948e179af6455a","repo":"koala73/worldmonitor","slug":"could-not-resolve-json-stringify-echocountryinpu","errorCode":null,"errorMessage":"Could not resolve ${JSON.stringify(echoCountryInput(raw))} to a country. ${COUNTRY_ARG_HINT}","messagePattern":"Could not resolve (.+?) to a country\\. (.+?)","errorType":"validation","errorClass":"RpcValidationError","httpStatus":400,"severity":"error","filePath":"api/mcp/registry/rpc-tools.ts","lineNumber":90,"sourceCode":"// not pick freely.\n\n/**\n * Resolve a `country_code` tool argument, or throw the same structured 400 the\n * downstream proto would have raised — reaching the agent as JSON-RPC -32602\n * with `error.data.violations[]`.\n *\n * The argument comes from an LLM, so it arrives as alpha-2, alpha-3, a country\n * name, or an alias interchangeably. It was previously coerced with\n * `.toUpperCase().slice(0, 2)`, which is silently wrong rather than lossy: the\n * proto only enforces `^[A-Z]{2}$`, so a truncated NAME passes validation and\n * answers for a different country — `Iraq` was served as Iran, `China` as\n * Switzerland (WORLDMONITOR-Y2). Failing loudly on the genuinely unresolvable\n * remainder is what lets an agent correct itself.\n */\nfunction requireCountryCode(raw: unknown, operation: string): string {\n  const resolved = resolveCountryCode(raw);\n  if (resolved) return resolved;\n  throw new RpcValidationError(operation, [{\n    field: 'country_code',\n    description: `Could not resolve ${JSON.stringify(echoCountryInput(raw))} to a country. ${COUNTRY_ARG_HINT}`,\n  }]);\n}\n\ntype DigestItemForBrief = {\n  title?: string;\n  snippet?: string;\n  source?: string;\n  link?: string;\n  url?: string;\n  publishedAt?: string | number;\n  pubDate?: string | number;\n  date?: string | number;\n  // Emitted by toProtoItem in server/worldmonitor/news/v1/list-feed-digest.ts\n  // for every digest item, and dropped on the way to an agent until #4925.\n  corroborationCount?: number;\n  storyMeta?: {","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/koala73/worldmonitor/blob/9361220cc013571781071f0206e4d80fd14b2f7f/api/mcp/registry/rpc-tools.ts#L72-L108","documentation":"requireCountryCode() resolves a caller-supplied country argument (name, code, alias) via resolveCountryCode(); if resolution fails it throws RpcValidationError with a field-level description including the echoed (safe, JSON-stringified) input and COUNTRY_ARG_HINT. It fails loudly so an agent can self-correct its arguments.","triggerScenarios":"Calling any MCP RPC tool whose handler calls requireCountryCode (directly or via countryCode()/code()) with a raw value that resolveCountryCode cannot map — misspelled country names, lowercase or non-alpha-2 codes, unknown aliases, non-string types like numbers or objects.","commonSituations":"An LLM agent passing 'Swiss' or 'CHN'-style typo codes; passing a numeric ISO 3166-1 numeric code; passing localized country names; passing null/undefined when the parameter was optional upstream.","solutions":["Pass a valid ISO 3166-1 alpha-2 code (e.g. \"CH\", \"US\") — the most reliable form.","Use the exact country name or alias supported by resolveCountryCode; consult COUNTRY_ARG_HINT in the error message for accepted formats.","Trim whitespace and fix casing (resolution is typically case-insensitive but exact spelling matters).","If the entity genuinely has no country code (e.g. an EU-wide query), use the tool's non-country variant or preset parameter instead."],"exampleFix":"// before\ncallTool('get-country-brief', { country_code: 'Swiss' })\n// after\ncallTool('get-country-brief', { country_code: 'CH' })","handlingStrategy":"validation","validationCode":"const resolved = resolveCountryCode(raw);\nif (!resolved) {\n  throw new Error(`\"${raw}\" is not a recognized country; pass an ISO 3166-1 alpha-2 code like \"CH\"`);\n}","typeGuard":"function isAlpha2(v: unknown): v is string {\n  return typeof v === 'string' && /^[A-Za-z]{2}$/.test(v);\n}","tryCatchPattern":"try {\n  const cc = requireCountryCode(raw, 'get-country-brief');\n} catch (err) {\n  if (err instanceof RpcValidationError) {\n    // inspect err.fields / description; retry once with a normalized alpha-2 code\n  } else throw err;\n}","preventionTips":["Always pass uppercase ISO 3166-1 alpha-2 codes to MCP country tools.","Normalize user/agent input through resolveCountryCode before dispatching RPCs.","Read COUNTRY_ARG_HINT in the error for accepted formats.","Trim and uppercase strings at the input boundary."],"tags":["validation","mcp","rpc","country-code","input"],"backgroundTag":"rpc-validation-error","analyzedSha":"9361220cc013571781071f0206e4d80fd14b2f7f","analyzedAt":"2026-09-01T10:32:37.851Z","contentChangedAt":"2026-09-01T10:32:37.851Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}