Repository navigation
[quality] validate-radar-reports.mjs crashes instead of reporting a truthy non-array radarReports #497
Description
Finding
scripts/validate-radar-reports.mjs reports the wrong thing when
data/radar-reports.json holds a truthy non-array radarReports value: it
dies with an unhandled TypeError and a stack trace, instead of printing the
validation error it already collected.
Line 22 collects the error correctly:
if (!Array.isArray(data.radarReports) || !data.radarReports.length)
errors.push({ … message: 'radarReports must be a non-empty array' });but line 30 then iterates before reportAndExit ever runs:
for (const entry of data.radarReports || []) {|| [] only rescues a falsy value. {}, "…" and 42 are all truthy and
all non-iterable, so the process crashes at line 30 and the collected message is
never printed.
Reproduction
Observed at 8c089a0 (origin/main), Node v26.8.2, 2026-09-23:
runScriptWithFixtures('validate-radar-reports.mjs', {
'data/radar-reports.json': JSON.stringify({
generatedAt: '2026-08-07T00:00:00.000Z',
sourceUrl: 'https://www.cncf.io/reports',
radarReports: { '1': {} },
}),
});scripts/validate-radar-reports.mjs:30
for (const entry of data.radarReports || []) {
^
TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
Both outcomes exit non-zero, so this is not a missed failure — it is a
diagnosability defect. scripts/collect-radar-reports.mjs writes this file, and
an upstream shape change there would surface to a maintainer as a stack trace
pointing at the validator rather than as radarReports must be a non-empty array pointing at the data.
Recommendation
One line — stop the loop from re-deriving the guard that line 22 already made:
for (const entry of Array.isArray(data.radarReports)
? data.radarReports
: []) {Sibling validators should be checked for the same X || [] shape after an
Array.isArray guard before this is considered done.
-
scripts/validate-radar-reports.mjs:30iterates only a checked array. - A truthy non-array
radarReportsexits 1 withradarReports must be a non-empty arrayon stderr and no stack trace. - The remaining
scripts/validate-*.mjsfiles are audited for the same
pattern, and any found are fixed in the same change.
Why this is filed rather than fixed
This is a change to a production script, not to tests. The quality agent's lane
is testing-only, so it cannot PR the fix. A human maintainer or a
production-lane agent needs to land it.
It was found while writing #495 / #496, which covers that validator's error
branches. #496 deliberately exercises the !Array.isArray branch with null
(falsy, so it exits cleanly) rather than asserting the crash, because a test
asserting a stack trace would cement this behaviour. Once the line above lands,
that test can be widened to {} in the same change.
Priority
- Impact: medium — a validator that misreports a data-shape failure as its own
crash costs maintainer time at exactly the moment the data is already broken. - Effort: low — one line, plus a short audit of the sibling validators.
🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: fd8cc55
— hive: agent=quality backend=copilot model=claude-opus-5
Activity