koala73/worldmonitor · warning · RpcValidationError

No focal-point coverage for ${countryCode}: that country is

Error message

No focal-point coverage for ${countryCode}: that country is absent from the entity registry.

What it means

The get-focal-points MCP tool validates its country_code against the shared entity registry (getSharedEntityIndex). If a non-empty country_code is not present in byId with type 'country', it throws an RpcValidationError stating there is no focal-point coverage for that country. This separates 'registry has no such country' from 'registry has the country but no focal points'.

Solutions

  1. Send an ISO 3166-1 alpha-2 code that exists in the entity registry (verify via the registry/lookup tool)
  2. Check for typos and use sovereign-state codes, not subdivision codes ('US' not 'US-CA')
  3. Refresh the shared entity registry seed if the country genuinely should exist
  4. If you want all focal points, omit country_code instead of passing an invalid one

Example fix

// before
getFocalPoints({ country_code: 'UK' }); // not in registry
// after
getFocalPoints({ country_code: 'GB' });
Defensive patterns

Strategy: validation

Validate before calling

// pre-check against the registry before calling
const registry = getSharedEntityIndex();
if (code && registry.byId.get(code)?.type !== 'country') throw new Error(`unknown country: ${code}`);

Type guard

function isRegisteredCountry(code, index) { return typeof code === 'string' && index.byId.get(code)?.type === 'country'; }

Try / catch

try { return await getFocalPoints(params); } catch (e) { if (e instanceof RpcValidationError) return { focalPoints: [], reason: 'country_not_in_registry' }; throw e; }

Prevention

When it happens

Trigger: Calling get-focal-points with a country_code string that is not a key in the entity registry (typo'd code, deprecated country code, subdivision-level code like 'US-CA', or a code only valid in another dataset). Empty/whitespace codes skip the check and return the unfiltered set.

Common situations: LLM callers inventing country codes or passing region codes; registry seed out of date so recently changed codes (e.g. ISO renames) are absent; clients reusing codes from a non-registry dataset.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of koala73/worldmonitor@7d06c8633d (2026-09-15). Data as JSON: /api/errors/1a71891418abe057. Report an issue: GitHub.

Appendix: source

Thrown at api/mcp/registry/analysis-tools.ts:417

                signals_total: { type: 'number' },
                signals_mapped: { type: 'number' },
                signals_unmapped: { type: 'number' },
              },
            },
          },
          required: [],
        },
      },
      required: ['cached_at', 'stale', 'data'],
    },
    annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
    _execute: async (params) => {
      const rawCountry = params.country_code;
      const countryCode = rawCountry == null || (typeof rawCountry === 'string' && !rawCountry.trim())
        ? '' : requireCountryCode(rawCountry, 'get-focal-points');
      const index = getSharedEntityIndex();
      if (countryCode && index.byId.get(countryCode)?.type !== 'country') {
        throw new RpcValidationError('get-focal-points', [{
          field: 'country_code',
          description: `No focal-point coverage for ${countryCode}: that country is absent from the entity registry.`,
        }]);
      }
      const limit = resolveLimit(params.limit, 10);
      const keys = ['news:insights:v1', 'intelligence:cross-source-signals:v1', CII_RISK_SCORE_CACHE_KEYS.live];
      const checks: FreshnessCheck[] = [
        { key: 'seed-meta:news:insights', maxStaleMin: 30 },
        { key: 'seed-meta:intelligence:cross-source-signals', maxStaleMin: 30 },
        { key: 'seed-meta:intelligence:risk-scores', maxStaleMin: 30, minRecordCount: 3 },
      ];
      const { payloads: [insights, crossSource, riskScores], freshness } = await readCachesWithFreshness(keys, checks);
      requireAnyInput(
        [insights, crossSource, riskScores],
        freshness,
        'No focal-point input feeds are available',
      );

View on GitHub (pinned to 7d06c8633d)