Skip to content

[quality] validate-radar-reports.mjs crashes instead of reporting a truthy non-array radarReports #497

Closed

Description

@hivecommons-hive

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:30 iterates only a checked array.
  • A truthy non-array radarReports exits 1 with radarReports must be a non-empty array on stderr and no stack trace.
  • The remaining scripts/validate-*.mjs files 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent/qualityApproved by a Hive merger/owner for auto-merge on green CIqualityApproved by a Hive merger/owner for auto-merge on green CI

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions