koala73/worldmonitor · warning · ValidationError
Unknown chokepoint ID: ${invalidCp}
Error message
Unknown chokepoint ID: ${invalidCp} What it means
registerWebhook validates every entry of chokepointIds against VALID_CHOKEPOINT_IDS — the Set built from CHOKEPOINT_REGISTRY (server/_shared/chokepoint-registry via webhook-shared.ts:5) — and rejects with a 400 naming the first offending id. This keeps subscriptions bound to real maritime chokepoints so alert delivery never fans out to unknown ids.
Source
Thrown at server/worldmonitor/shipping/v2/register-webhook.ts:65
await requirePremiumRpcAccess(ctx.request, ApiError, 'PRO subscription required');
const callbackUrl = (req.callbackUrl ?? '').trim();
if (!callbackUrl) {
throw new ValidationError([{ field: 'callbackUrl', description: 'callbackUrl is required' }]);
}
try {
await assertCallbackUrlRegistrationSafe(callbackUrl);
} catch (error) {
const message = error instanceof Error ? error.message : 'callbackUrl is not allowed';
throw new ValidationError([{ field: 'callbackUrl', description: message }]);
}
const chokepointIds = Array.isArray(req.chokepointIds) ? req.chokepointIds : [];
const invalidCp = chokepointIds.find(id => !VALID_CHOKEPOINT_IDS.has(id));
if (invalidCp) {
throw new ValidationError([
{ field: 'chokepointIds', description: `Unknown chokepoint ID: ${invalidCp}` },
]);
}
// alert_threshold is `optional int32` (#3242 followup #4) — undefined means
// the partner omitted the field, so apply the legacy default of 50. An
// explicit 0 is preserved (deliver every alert). The 0..100 range is
// normally enforced by buf.validate at the wire layer, but we re-enforce
// it here so direct handler calls (internal jobs, test harnesses, future
// transports that bypass buf.validate) can't store out-of-range values.
const alertThreshold = req.alertThreshold ?? 50;
if (alertThreshold < 0 || alertThreshold > 100) {
throw new ValidationError([
{ field: 'alertThreshold', description: 'alertThreshold must be between 0 and 100' },
]);
}
const ownerTag = await callerFingerprint(ctx.request, apiKeyResult.credential);View on GitHub (pinned to eeab0a219f)
Solutions
- Take the offending id echoed in the error message and replace it with a current CHOKEPOINT_REGISTRY id from the registry/docs
- Source chokepointIds dynamically (fetch the current chokepoint list) instead of hardcoding
- Match exact casing and trim whitespace before sending
Example fix
// before
await registerWebhook({ callbackUrl, chokepointIds: ['panama', 'suez'] });
// after
await registerWebhook({ callbackUrl, chokepointIds: ['panama-canal', 'suez-canal'] }); // exact registry ids Defensive patterns
Strategy: validation
Validate before calling
const VALID = new Set(['panama-canal', 'suez-canal' /* keep in sync with CHOKEPOINT_REGISTRY */]);
const bad = ids.filter(id => !VALID.has(id)); if (bad.length) throw new RangeError(`Unknown chokepoint ids: ${bad.join(', ')}`); Try / catch
catch (e) { const m = /Unknown chokepoint ID: (.+)/.exec(e?.details?.[0]?.description ?? ''); if (m) { replace m[1] with a registry id and re-submit } else throw e; } Prevention
- Fetch chokepoint ids from the current registry instead of hardcoding
- Keep partner docs in sync when registry ids change
- Trim and case-match ids exactly before sending
When it happens
Trigger: POST RegisterWebhook with a chokepointIds entry that is not a registry id: wrong slug form ('panama' vs the registered id), an id from an older registry version after renames, wrong casing, or trailing whitespace. The find() short-circuits on the first invalid id and echoes it in the message.
Common situations: Partner integration built against stale documentation; ids copied from a different API surface; registry renamed ids in a deploy; hand-built request objects in tests with placeholder ids.
Related errors
- callbackUrl is required
- callbackUrl is not allowed
- alertThreshold must be between 0 and 100
- fromIso2 and toIso2 must be valid 2-letter ISO country codes
- callbackUrl is not a valid URL
AI-assisted analysis of koala73/worldmonitor@eeab0a219f (2026-08-21).
Data as JSON: /api/errors/2a5ea18e2392be71.
Report an issue: GitHub.