koala73/worldmonitor · error · ValidationError
chokepointId must be a canonical chokepoint id
Error message
chokepointId must be a canonical chokepoint id
What it means
getChokepointDependencies normalizes chokepointId to lowercase and requires it to match /^[a-z0-9_-]{1,80}$/ (a canonical chokepoint id like 'suez' or 'strait-of-hormuz'). Non-matching ids throw this ValidationError before any cache lookup.
Source
Thrown at server/worldmonitor/supply-chain/v1/get-chokepoint-dependencies.ts:31
chokepointDependencyShardKey,
resolvePageSize,
enforceDependencyRedistributionPolicy,
hasCurrentRedistributionPolicy,
isMatchingShard,
locateEntityShard,
mapChokepointDependency,
type RawVulnerabilityCohort,
type RawChokepointShard,
stringValue,
} from './_vulnerability-projection';
export async function getChokepointDependencies(
ctx: ServerContext,
req: GetChokepointDependenciesRequest,
): Promise<GetChokepointDependenciesResponse> {
const chokepointId = (req.chokepointId || '').trim().toLowerCase();
if (!/^[a-z0-9_-]{1,80}$/.test(chokepointId)) {
throw new ValidationError([{ field: 'chokepointId', description: 'chokepointId must be a canonical chokepoint id' }]);
}
const persistedPayload = await getCachedJson(VULNERABILITY_COHORT_KEY, true)
.catch(() => null) as RawVulnerabilityCohort | null;
const payload = hasCurrentRedistributionPolicy(persistedPayload) ? persistedPayload : null;
let chokepoint = payload?.chokepoints?.[chokepointId];
let shardUnavailable = false;
if (payload && !payload.chokepoints) {
const located = locateEntityShard(
payload,
payload.chokepointIds,
chokepointId,
chokepointDependencyShardKey,
);
if (located.status === 'unavailable') {
shardUnavailable = true;
} else if (located.status === 'read') {
const shard = await getCachedJson(located.key, true)View on GitHub (pinned to 9361220cc0)
Solutions
- Use a canonical lowercase id (e.g. 'suez', 'panama', 'strait-of-hormuz') from the chokepoint seed/reference data
- Sanitize: trim, lowercase, replace spaces with '-' before calling
- Validate with /^[a-z0-9_-]{1,80}$/ on the client
- Check the chokepoint exists in the vulnerability cohort payload before calling
Example fix
// before
await getChokepointDependencies({ chokepointId: 'Suez Canal' })
// after
const id = String(raw).trim().toLowerCase().replace(/\s+/g, '-');
if (!/^[a-z0-9_-]{1,80}$/.test(id)) throw new Error('invalid chokepoint id');
await getChokepointDependencies({ chokepointId: id }) Defensive patterns
Strategy: validation
Validate before calling
function isValidChokepointId(v) {
const id = String(v || '').trim().toLowerCase();
return /^[a-z0-9_-]{1,80}$/.test(id);
} Type guard
function isCanonicalChokepointId(v) {
return typeof v === 'string' && /^[a-z0-9_-]{1,80}$/.test(v);
} Try / catch
try {
return await getChokepointDependencies({ chokepointId });
} catch (e) {
if (e.name === 'ValidationError' && e.field === 'chokepointId') {
return null;
}
throw e;
} Prevention
- Source chokepoint ids from the canonical reference/seed data, never display labels
- Normalize ids (trim, lowercase, dashes for spaces) at the UI boundary
- Keep ids under 80 characters and ASCII-only
- Validate the id exists in the cohort payload for a better UX than the throw
When it happens
Trigger: Passing display names ('Suez Canal'), ids with spaces or special characters, empty/missing chokepointId, or ids longer than 80 characters.
Common situations: UI passing human-readable labels instead of canonical ids; ids sourced from free text; uppercase ids (regex is lowercase-only after toLowerCase, but non-ASCII or symbols fail); stale ids from an old seed dataset.
Related errors
- iso2 must be a 2-letter uppercase ISO country code
- iso2 must be a 2-letter uppercase ISO country code
- Invalid scorecard bloc selection.
- countryCode must be a 2-letter ISO 3166-1 alpha-2 code
- iso2 must be a 2-letter uppercase ISO country code
AI-assisted analysis of koala73/worldmonitor@9361220cc0 (2026-09-01).
Data as JSON: /api/errors/6f5d38cf8bfb8b6c.
Report an issue: GitHub.