koala73/worldmonitor · error
EONET malformed event
Error message
EONET malformed event
What it means
Thrown by fetchEonet after the event loop: validEonetRecords(events) returned false, meaning the assembled EONET record list failed the seeder's aggregate validity check (e.g. too few valid records). This guards against shipping an empty or implausibly small snapshot after per-event validation passed or skipped data.
Solutions
- Log events.length and the post-filter count to see whether the API returned nothing or everything was filtered.
- Retry later — EONET occasionally returns empty result sets during maintenance.
- Verify the EONET request URL/params (days window, status=open) are correct and not restricting results to zero.
- If a legitimately quiet period, consider lowering the validEonetRecords threshold or making it configurable.
Example fix
// before
if (!validEonetRecords(events)) throw new Error('EONET malformed event');
// after
if (!validEonetRecords(events)) {
console.warn(`EONET produced only ${events.length} valid records`);
throw new Error(`EONET malformed event (got ${events.length} records)`);
} Defensive patterns
Strategy: fallback
Validate before calling
const preview = await fetchEventSourceJson('eonet', url, fetchFn); if (!Array.isArray(preview?.events) || preview.events.length === 0) console.warn('EONET returned no events; seed will fail validity check'); Type guard
function hasEnoughRecords(events) { return Array.isArray(events) && events.length > 0; } Try / catch
try { const events = await fetchEonet(fetchFn); } catch (e) { if (e.message === 'EONET malformed event') { console.error('EONET aggregate validity failed; falling back to previous snapshot'); return previousSnapshot; } throw e; } Prevention
- Keep the previous successful snapshot and serve it when the fresh fetch fails validity
- Log the event count before and after filtering to distinguish outage from over-filtering
- Make the minimum-record threshold configurable for legitimately quiet periods
- Monitor EONET status endpoints before scheduled seeds
When it happens
Trigger: The full EONET fetch produced an events array that fails validEonetRecords — typically zero or far fewer valid records than the threshold after filtering out earthquakes and Point-only records.
Common situations: EONET API outage or returning an empty events list; all events filtered out as earthquakes; a network proxy returning an empty-but-valid JSON body; wrong API URL/env producing no events.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- disruptionPct must be an integer from 0 to 100 for a…
- EONET malformed event category
- EONET malformed event geometry
- Expected a supported two-letter market code
- Expected an array of Sentry issues. A Sentry error body is…
AI-assisted analysis of koala73/worldmonitor@e586b8b4b8 (2026-09-22).
Data as JSON: /api/errors/d2df7b573bcf9dd3.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/seed-natural-events.mjs:286
const source = event.sources?.[0];
events.push({
id: event.id || '',
title: event.title || '',
description: event.description || '',
category: normalizedCategory,
categoryTitle: category.title || '',
lat,
lon,
date: eventDate.getTime(),
magnitude: latestGeo.magnitudeValue ?? 0,
magnitudeUnit: latestGeo.magnitudeUnit || '',
sourceUrl: source?.url || '',
sourceName: source?.id || '',
closed: event.closed !== null,
});
}
if (!validEonetRecords(events)) throw new Error('EONET malformed event');
return events;
}
function classifyWind(kt) {
if (kt >= 137) return { category: 5, classification: 'Category 5' };
if (kt >= 113) return { category: 4, classification: 'Category 4' };
if (kt >= 96) return { category: 3, classification: 'Category 3' };
if (kt >= 83) return { category: 2, classification: 'Category 2' };
if (kt >= 64) return { category: 1, classification: 'Category 1' };
if (kt >= 34) return { category: 0, classification: 'Tropical Storm' };
return { category: 0, classification: 'Tropical Depression' };
}
function parseNhcAdvisoryDate(value) {
if (typeof value !== 'string') return new Date(value).getTime();
const match = value.match(/^(\d{1,2})(\d{2}) (AM|PM) ([A-Z]{3,4}) (Sun|Mon|Tue|Wed|Thu|Fri|Sat) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{1,2}) (\d{4})$/);
if (!match) return new Date(value).getTime();View on GitHub (pinned to e586b8b4b8)