koala73/worldmonitor · error · RpcValidationError
provide exactly one of country_code, preset, or members.
Error message
provide exactly one of country_code, preset, or members.
What it means
The get-five-factor-scorecard tool requires exactly one of three mutually exclusive selectors: country_code, preset, or members. The handler counts how many are present (non-empty) and throws RpcValidationError when the count is not exactly 1 — i.e. zero selectors or more than one selector was supplied.
Source
Thrown at api/mcp/registry/rpc-tools.ts:2153
},
},
required: [],
oneOf: [
{ required: ['country_code'] },
{ required: ['preset'] },
{ required: ['members'] },
],
},
outputSchema: FIVE_FACTOR_SCORECARD_OUTPUT_SCHEMA,
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
_coverageKeys: ['scorecard:five-factor:v1', 'seed-meta:scorecard:five-factor'],
_execute: async (params, base, context) => {
const countryCode = argStr(params.country_code).trim().toUpperCase();
const preset = argStr(params.preset).trim().toUpperCase();
const members = Array.isArray(params.members) ? params.members : [];
const selectors = Number(countryCode.length > 0) + Number(preset.length > 0) + Number(members.length > 0);
if (selectors !== 1) {
throw new RpcValidationError('get-five-factor-scorecard', [{
field: 'selection',
description: 'provide exactly one of country_code, preset, or members.',
}]);
}
const q = new URLSearchParams();
let path: string;
if (countryCode) {
if (!/^[A-Z]{2}$/.test(countryCode)) {
throw new RpcValidationError('get-five-factor-scorecard', [{
field: 'country_code',
description: 'must be an ISO 3166-1 alpha-2 country code.',
}]);
}
path = '/api/scorecard/v1/get-five-factor-scorecard';
q.set('countryCode', countryCode);
} else {
path = '/api/scorecard/v1/get-bloc-scorecard';View on GitHub (pinned to 9361220cc0)
Solutions
- Send exactly one selector: either country_code, or preset, or members — delete the others from the request.
- For a single country use country_code: 'DE'; for a predefined basket use preset; for an ad-hoc group use members only.
- If building params programmatically, construct the params object conditionally so only one key is ever set.
- Empty strings count as absent — ensure the chosen selector is actually non-empty (argStr(...).trim() and members.length > 0).
Example fix
// before
callTool('get-five-factor-scorecard', { country_code: 'DE', preset: 'G10' })
// after
callTool('get-five-factor-scorecard', { country_code: 'DE' }) Defensive patterns
Strategy: validation
Validate before calling
const selectors = ['country_code', 'preset', 'members'].filter((k) => {
const v = params[k];
return Array.isArray(v) ? v.length > 0 : typeof v === 'string' && v.trim().length > 0;
});
if (selectors.length !== 1) throw new Error(`exactly one of country_code, preset, members required; got [${selectors}]`); Type guard
function hasExactlyOneSelector(p: { country_code?: string; preset?: string; members?: unknown[] }): boolean {
const n = Number(!!p.country_code?.trim()) + Number(!!p.preset?.trim()) + Number((p.members?.length ?? 0) > 0);
return n === 1;
} Try / catch
try {
return await callTool('get-five-factor-scorecard', params);
} catch (err) {
if (err instanceof RpcValidationError && err.fields?.[0]?.field === 'selection') {
// rebuild params with a single selector and retry once
} else throw err;
} Prevention
- Build scorecard params conditionally so only one selector key is ever present.
- Never spread a previous query's params into a new scorecard call.
- Remember empty strings and empty arrays count as absent.
- Document selector exclusivity in tool-calling agent prompts.
When it happens
Trigger: Calling get-five-factor-scorecard with: none of the three fields set; two or three set at once (e.g. both country_code and preset); members provided as an array alongside country_code; or all fields present but empty strings/empty array (count 0).
Common situations: An agent template that fills multiple selector fields by default; a UI passing through stale params from a previous query type; confusion between the single-country and group (preset/members) variants of the scorecard API.
Related errors
- Could not resolve ${JSON.stringify(echoCountryInput(raw))} t
- get_intel_timeline requires at least one of domain ("conflic
- ${label} HTTP 400
- country must be an ISO 3166-1 alpha-2 country code, e.g. "UA
- get-intel-timeline: domain Required unless country is set. O
AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-09-01).
Data as JSON: /api/errors/696639a28e053ede.
Report an issue: GitHub.