fix: guard _classify_completed_outcomes against non-dict rewards - #1054
Conversation
Previously, a truthy non-dict value in the 'rewards' field of result.json
(e.g. bare float 1.0, int, bool, list) caused an uncaught AttributeError
in _classify_completed_outcomes, crashing the entire evaluation run before
any new tasks could execute.
Root cause: the two-step pattern
rewards = r.get('rewards') if isinstance(r, dict) else None
reward = rewards.get('reward') if rewards else None
only guards against falsy values; a truthy non-dict (e.g. 1.0) passes the
'if rewards' check and then blows up on .get().
Fixes:
1. Import extract_reward from benchflow._utils.scoring — it already
handles None, dict, and non-dict values safely.
2. Replace the two-liner in _classify_completed_outcomes with:
reward = extract_reward(r) if isinstance(r, dict) else None
3. Add a logger.warning in _get_completed_tasks when rewards is a
non-dict truthy value, so operators can identify malformed result
files without a crash.
The fix is backwards-compatible: valid dict-shaped rewards are unchanged;
falsy non-dict values were already silently treated as errored and still
are (with a warning now); truthy non-dict values no longer crash.
|
/devin review |
|
@bingran-you can you take a look at this PR (and the issue that it fixes) and if it counts as infra against the associated miscellaneous issue? If yes, how do we get devin to retrigger the automated review / tests? |
|
@VaisakhiMishra Reproduced the issue A/B against the merge-base and verified the fix end to end. With a malformed
I also verified this using a real Docker oracle rollout: after changing only the produced One blocker before merge:
This is the same command used by the CI format-check step, so the branch needs to be formatted before approval. The equivalent malformed-rewards crash still exists in Once the formatting gate is clean, this looks good from my side. |
|
@Galius5136 thank you for the quick review! I have confirmed what you see |
|
Confirmed on 1fa95a2 — |
|
@Galius5136 I resolved the conflicts, what would be the next step to merge? (I don't have permissions to merge or run workflows) |
Previously, a truthy non-dict value in the 'rewards' field of result.json (e.g. bare float 1.0, int, bool, list) caused an uncaught AttributeError in _classify_completed_outcomes, crashing the entire evaluation run before any new tasks could execute.
How to reproduce the crash (pre-fix)
Can we make this bug fix as part of https://github.com/benchflow-ai/FrontierPhysics/issues/125 or should I open a separate issue to track this fix?
Root cause:
only guards against falsy values; a truthy non-dict (e.g. 1.0) passes the
if rewardscheck and then fails on .get().Fixes:
extract_rewardfrombenchflow._utils.scoring— it already handles None, dict, and non-dict values safely._classify_completed_outcomeswith:logger.warningin_get_completed_taskswhen rewards is a non-dict truthy value, so operators can identify malformed result files without a crash. The fix is backwards-compatible: valid dict-shaped rewards are unchanged; falsy non-dict values were already silently treated as errored and still are (with a warning now); truthy non-dict values no longer crash.uvx ruff check .failure forsrc/benchflow/contracts/user.py