Skip to content

Handle unrecognized probes and detectors in report digest generation#1663

Open
precognitivem0nk wants to merge 1 commit intoNVIDIA:mainfrom
precognitivem0nk:fix/report-digest-crash-1024
Open

Handle unrecognized probes and detectors in report digest generation#1663
precognitivem0nk wants to merge 1 commit intoNVIDIA:mainfrom
precognitivem0nk:fix/report-digest-crash-1024

Conversation

@precognitivem0nk
Copy link
Copy Markdown

Fixes #1024
The three PluginCache.plugin_info() call sites in report_digest.py crash with a ValueError when a report references a probe or detector that no longer exists in the current codebase (e.g. due to a rename between versions).
This PR wraps each call in try/except, logs a warning, and continues report generation with placeholder values instead of crashing.
Changes:

_init_populate_result_db (line ~131): falls back to empty tags, grouping the probe under "other"
_get_probe_info (line ~255): uses the classpath as description, empty tags, and None tier
_get_probe_detector_details (line ~305): uses the detector name as its description

Tested with a JSONL file referencing a nonexistent probe class. Before the fix it crashed with ValueError. After the fix it generates a valid HTML report and logs a warning.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 1, 2026

DCO Assistant Lite bot All contributors have signed the DCO ✍️ ✅

@precognitivem0nk
Copy link
Copy Markdown
Author

I have read the DCO Document and I hereby sign the DCO

Copy link
Copy Markdown
Collaborator

@jmartin-tech jmartin-tech left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for taking a look at this.

I would suggest that digest_report is not meant to be used in with reports from different versions at this time. The actual format for report.jsonl files is evolving rapidly between releases. While guards and warning are useful if the report cannot be processed accurately for a report from an older version the utility should simply report that it is not compatible and refuse to produce an html file. Creating an html report that results an incomplete or inaccurate view is generally discouraged.

In short I think this PR should likely redirect some, instead of suppressing the errors it should produce more clear indicators that the errors mean the report is not compatible wit the version being utilized. This may also benefit from adding a version compatibility check early in the process, the version check may need to be very strict until the project reaches a 1.0.0 release.

Since the methods impacted are used both during initial run digesting of the report and for post processing when utilizing as a utility this needs to be accounted for carefully as well.

@leondz may want to weigh in on this was well since he filed the original issue.

@precognitivem0nk
Copy link
Copy Markdown
Author

precognitivem0nk commented Apr 1, 2026 via email

@leondz
Copy link
Copy Markdown
Collaborator

leondz commented Apr 1, 2026

tagging related PR #1523

@jmartin-tech
Copy link
Copy Markdown
Collaborator

I would think the latter is acceptable, raising an exception with details when the data is not compatible and then catching that and reporting it would be acceptable.

@precognitivem0nk
Copy link
Copy Markdown
Author

Force-pushed a rework. Approach per @jmartin-tech's direction: raise on incompatibility, catch at the top level, refuse to produce HTML.

Changes:

  • New ReportIncompatibleError (GarakException subclass) with the offending classpath in the message
  • Three call sites in report_digest.py (_init_populate_result_db, _get_probe_info, _get_probe_detector_details) raise instead of suppressing
  • CLI entry point catches, prints a clear incompatibility message to stderr, exits 1 without writing HTML
  • rebuild_cis.py gets a matching except arm in its existing structured error handling

Call sites intentionally left alone:

  • command.py (in-run digest after a fresh scan): lets the exception propagate, since a just-generated report hitting this is an internal bug, not a version mismatch
  • aggregate_reports.py: existing version asserts above the build_digest call already guard against cross-report mismatches

Tests: new tests/analyze/test_report_digest.py with two cases (unknown probe, unknown detector); all 35 tests in tests/analyze/ pass locally.

Note: the force-push triggered DCO and CLAAssistant (both pass), but the build matrix didn't auto-run. Could a maintainer approve the workflow run when you get a chance?

@precognitivem0nk
Copy link
Copy Markdown
Author

Couple of points I should have flagged upfront:

  1. You also mentioned an early version compatibility check. I went with the per-plugin raise/catch since you said that was acceptable, but happy to add an early version gate on top (this PR or follow-up), your call.

  2. command.py currently lets the exception propagate on the assumption that a fresh-run digest hitting this is an internal bug, not the reporting: enable logging & skipping of unrecognised probes, detectors in digest generation #1024 version mismatch case. Happy to handle it explicitly too if you'd prefer.

cc @leondz in case the pivot from skip/log (original #1024 framing) to fail loudly needs your sign-off before I go further.

When a report.jsonl references a probe or detector that is not known
to the current garak install (typically because the report was
generated by a different version), the initial approach suppressed
the resulting ValueError and substituted placeholder metadata,
producing a partial HTML report.

Per reviewer feedback, partial reports are worse than failing: they
hide the version mismatch and can yield inaccurate output. This
change instead raises a new ReportIncompatibleError (a GarakException
subclass) with the offending classpath, and catches it at the CLI
entry point to print a clear incompatibility message and exit 1
without writing HTML.

rebuild_cis.py also catches the new exception in its existing
structured error handling.

command.py (in-run digest) intentionally lets the exception propagate,
since a just-generated report hitting this indicates an internal bug
rather than a version mismatch. aggregate_reports.py is left alone;
its existing version asserts already guard against cross-report
mismatches.

Fixes NVIDIA#1024

Signed-off-by: precognitivem0nk <rextedgorman@gmail.com>
@precognitivem0nk precognitivem0nk force-pushed the fix/report-digest-crash-1024 branch from 463516c to fdd2d38 Compare April 21, 2026 04:42
@precognitivem0nk
Copy link
Copy Markdown
Author

Rebased onto current main to resolve the conflict with #1672. Two behaviors worth flagging: (1) passing -t on an incompatible report now exits 1 with the incompatibility message instead of returning the embedded stale digest, and (2) taxonomy inheritance from the report setup (also from #1672) routes through the new incompatibility check cleanly, so users hit a clear error instead of a mislabeled digest. Full test suite in tests/analyze/ (126 tests, including upstream's new taxonomy tests from #1672) passes on the rebased tree.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

reporting: enable logging & skipping of unrecognised probes, detectors in digest generation

3 participants