koala73/worldmonitor · error · Error
Custom scorecard bloc members must belong to the public rank
Error message
Custom scorecard bloc members must belong to the public rankable country universe.
What it means
Even well-formed, unique, uppercase ISO-2 codes are only accepted if each belongs to the public rankable country universe (checked via isInRankableUniverse(member)). The scorecard ranks countries against a curated dataset universe; microstates, territories, or codes without underlying indicator data are excluded so blocs stay comparable. Codes outside the universe (e.g., 'VA', 'HK' depending on the current universe, or 'AQ') throw this error.
Source
Thrown at server/worldmonitor/scorecard/v1/_bloc-presets.ts:42
};
export function resolveBlocSelection(input: { preset?: string; members?: string[] }): ScorecardBlocSelection {
const preset = String(input.preset || '').trim();
const members = Array.isArray(input.members) ? input.members : [];
if (Boolean(preset) === (members.length > 0)) {
throw new Error('Select exactly one scorecard bloc preset or custom member list.');
}
if (preset) {
if (!(preset in SCORECARD_BLOC_PRESETS)) throw new Error(`Unknown scorecard bloc preset: ${preset}`);
return SCORECARD_BLOC_PRESETS[preset as ScorecardBlocPreset];
}
if (members.length < 2 || members.length > 30) throw new Error('Custom scorecard blocs require 2-30 members.');
if (members.some((member) => !/^[A-Z]{2}$/.test(member))) {
throw new Error('Custom scorecard bloc members must be uppercase ISO-2 codes.');
}
if (new Set(members).size !== members.length) throw new Error('Custom scorecard bloc members must be unique.');
if (members.some((member) => !isInRankableUniverse(member))) {
throw new Error('Custom scorecard bloc members must belong to the public rankable country universe.');
}
const sorted = [...members].sort();
return { id: `custom:${sorted.join('-')}`, label: sorted.join(' + '), members: sorted };
}
View on GitHub (pinned to 9361220cc0)
Solutions
- Filter members through the published rankable-universe list (or isInRankableUniverse if you can import it) before sending.
- Use the API's country listing (listScorableCountries / static index) to populate the picker so only rankable codes are offered.
- After filtering, confirm ≥2 members remain and meet all other rules; otherwise switch to a preset.
- Pin your client to the API version whose universe your lists were built against.
Example fix
// before
resolveBlocSelection({ members: ['US', 'VA', 'MC'] }); // throws: VA/MC not rankable
// after
const members = raw.filter((m) => isInRankableUniverse(m));
if (members.length >= 2) resolveBlocSelection({ members }); Defensive patterns
Strategy: validation
Validate before calling
const rankable = await fetchRankableUniverse(); // from listScorableCountries or static index
const members = raw.filter((m) => rankable.includes(m));
if (members.length < 2) throw new Error('not enough rankable members for a bloc'); Type guard
function isRankable(code: string, universe: ReadonlySet<string>): code is string {
return universe.has(code);
} Try / catch
try {
const bloc = await getBlocScorecard({ members });
} catch (err) {
if (err.message.includes('rankable country universe')) {
const excluded = members.filter((m) => !universe.has(m));
return badRequest({ excluded, hint: 'choose from listScorableCountries' });
}
throw err;
} Prevention
- Populate pickers from listScorableCountries, not raw ISO-3166 lists
- Filter territories/microstates out of custom selections
- Re-filter on API version upgrades (universe can change)
- Keep a cached copy of the rankable universe client-side for pre-validation
When it happens
Trigger: Calling getBlocScorecardWithReader with a custom list containing any non-rankable code: territories (e.g., 'GL', 'PR'), microstates ('MC', 'SM'), or any ISO-2 code absent from the published rankable universe, even if the rest of the list is valid.
Common situations: 1) A world country-picker lists all ISO-3166 entries including dependencies and microstates that the dataset doesn't rank; 2) universe changes between versions — a code previously rankable is dropped after a data-source revision; 3) users deliberately test edge codes ('AQ' Antarctica).
Related errors
- Select exactly one scorecard bloc preset or custom member li
- Unknown scorecard bloc preset: ${preset}
- Custom scorecard blocs require 2-30 members.
- Custom scorecard bloc members must be unique.
- Custom scorecard bloc members must be uppercase ISO-2 codes.
AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-09-01).
Data as JSON: /api/errors/6bf7b0fb64ac90f2.
Report an issue: GitHub.