koala73/worldmonitor · error · ApiError
Airport delay filters are not supported
Error message
Airport delay filters are not supported
What it means
The seed-only airport delay listing supports no filtering: pageSize must be 0, no cursor, region must be AIRPORT_REGION_UNSPECIFIED (or unset), and minSeverity must be FLIGHT_DELAY_SEVERITY_UNSPECIFIED (or unset). Any filter combination throws ApiError 400.
Solutions
- Call the endpoint with no region, minSeverity, cursor, or page_size filters and filter client-side
- Reset the proto message so unset/default enum values are not serialized onto the wire
- Drop cursor-based pagination; re-fetch the full list instead of resuming
- Send page_size=0 and leave all filter fields at their unspecified defaults
Example fix
// before
const req = { region: 'AIRPORT_REGION_EU', minSeverity: 'FLIGHT_DELAY_SEVERITY_MODERATE' };
// after
const req = { region: 'AIRPORT_REGION_UNSPECIFIED', minSeverity: 'FLIGHT_DELAY_SEVERITY_UNSPECIFIED' };
// then filter results in the client Defensive patterns
Strategy: validation
Validate before calling
const filterable = r => (r.pageSize ?? 0) === 0 && !r.cursor && (!r.region || r.region === 'AIRPORT_REGION_UNSPECIFIED') && (!r.minSeverity || r.minSeverity === 'FLIGHT_DELAY_SEVERITY_UNSPECIFIED');
if (!filterable(req)) throw new Error('filters unsupported'); Type guard
const isUnfilteredDelayRequest = (r) => (r.pageSize ?? 0) === 0 && r.cursor == null && (r.region == null || r.region === 'AIRPORT_REGION_UNSPECIFIED') && (r.minSeverity == null || r.minSeverity === 'FLIGHT_DELAY_SEVERITY_UNSPECIFIED');
Try / catch
try { return await listAirportDelays(ctx, req); } catch (e) { if (e instanceof ApiError && e.message === 'Airport delay filters are not supported') { return fetchAllAndFilterClientSide(); } throw e; } Prevention
- Filter airport delay results client-side, never server-side
- Reset proto enum fields to *_UNSPECIFIED instead of omitting only sometimes
- Drop cursor reuse from paged endpoints when calling this one
- Keep a typed request builder that forbids filter fields
When it happens
Trigger: GET with region=AIRPORT_REGION_EU, minSeverity=<non-unspecified>, cursor=<token>, or a decoded proto request carrying pageSize>0 / cursor, alone or combined.
Common situations: Reusing client code written for filterable list endpoints; proto clients that populate default-valued enum fields explicitly; retry logic replaying a cursor from a prior paged response.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Airport delay page_size must be 0
- deadlineMs must be a positive number
- Duplicate airport delay parameter
- Expected finite viewport coordinates
- Invalid airport delay route
AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-09-22).
Data as JSON: /api/errors/7bd1ff13cdd23746.
Report an issue: GitHub.
Appendix: source
Thrown at server/worldmonitor/aviation/v1/list-airport-delays.ts:52
const ALLOWED_QUERY_PARAMS = new Set(['page_size', 'cursor', 'region', 'min_severity', 'jmespath', '_debug', 'rpc']);
export async function listAirportDelays(
ctx: ServerContext,
req: ListAirportDelaysRequest,
): Promise<ListAirportDelaysResponse> {
const seenParams = new Set<string>();
for (const [key, value] of new URL(ctx.request.url).searchParams) {
if (!ALLOWED_QUERY_PARAMS.has(key)) throw new ApiError(400, `Unsupported airport delay parameter: ${key}`, '');
if (seenParams.has(key)) throw new ApiError(400, `Duplicate airport delay parameter: ${key}`, '');
seenParams.add(key);
if (key === 'page_size' && value !== '0') throw new ApiError(400, 'Airport delay page_size must be 0', '');
if (key === 'rpc' && value !== 'list-airport-delays') throw new ApiError(400, 'Invalid airport delay route', '');
}
if ((req.pageSize ?? 0) !== 0 || req.cursor
|| (req.region && req.region !== 'AIRPORT_REGION_UNSPECIFIED')
|| (req.minSeverity && req.minSeverity !== 'FLIGHT_DELAY_SEVERITY_UNSPECIFIED')) {
throw new ApiError(400, 'Airport delay filters are not supported', '');
}
// 1. FAA (US) — seed-only read
// faaSourceCovered = the seed cache hit AND returned a valid alerts array.
// A miss/parse-error means we have no telemetry for any FAA airport this
// tick — we MUST NOT publish synthetic "normal" rows for them. See #3707.
// PERF: the three inputs below are independent (different Redis keys / an
// independent fetcher) and merge only afterwards — start them concurrently
// instead of paying three serial round-trips per request.
const faaRead = (async (): Promise<{ faaAlerts: AirportDelayAlert[]; faaSourceCovered: boolean; available: boolean }> => {
let faaAlerts: AirportDelayAlert[] = [];
let faaSourceCovered = false;
try {
const seed = await readCachedJson(FAA_CACHE_KEY, true);
const seedData = seed.status === 'hit' ? seed.value as { alerts?: unknown[] } | null : null;
if (seedData && Array.isArray(seedData.alerts) && seedData.alerts.every(isValidAirportDelayAlert)) {
faaSourceCovered = true;
faaAlerts = seedData.alerts!
.map(a => {View on GitHub (pinned to e586b8b4b8)