R/4D7

Every open code reinforcement learning stack audited scores a crash and a wrong answer identically

A program that halts on a violated invariant and a program that returns a confident wrong answer are different events with different costs. In the reward paths of the open training stacks read for this artifact they are one number, because the outcome of execution is reduced to whether the tests passed. Recorded here: the engineering canon that treats a violated invariant as grounds for halting, the measurements of how far ordinary practice sits from it, and the reward code under which suppressing an error state scores no worse than surfacing it, and sometimes better.

part one

Scope

This artifact records the state of error-handling doctrine, its measured prevalence in source corpora, and the reward structures of open code reinforcement learning stacks as of August 2026. Published literature, industry corpus research, and four training repositories read at their default branches on 2026-08-15 are compiled. It contributes one original measurement, the audit in part six, and adjudicates nothing.

Two conditions are distinguished throughout, and the distinction is load-bearing for everything that follows.

  1. Expected environmental failure. A network is unavailable, a file is absent, user input is malformed. These outcomes are part of a program’s specified behaviour, and handling them is that specification being met.
  2. Invariant violation. A collection the author established cannot be empty is empty; a state machine occupies two states at once. These outcomes are defects. Execution past one of them proceeds on an assumption known to be false.

A handler written as except Exception covers both conditions with one clause, so a program cannot act differently on them. The literature in part three measures how common that clause is; the reward code in part six shows the same collapse at the point where model behaviour is scored.

part two

The canon on invariant violation

The position that a program should halt on a violated invariant is long established in the literature and holds in infrastructure practice.

Armstrong’s design for Erlang rejects defensive handling inside a process: a process meeting an unexpected condition terminates, and a supervisor restarts it from a known state.1 The architectural requirement is that the terminating unit be small, cheap, and supervised, rather than that termination be frequent. Candea and Fox generalised this as crash-only software, in which a program has one stop path and one start path, on the argument that a system already obliged to survive crashes gains nothing from a separate clean-shutdown path.2 The pattern is standard in infrastructure: supervisor trees, liveness-probe restarts, and write-ahead-log recovery all assume it.

Shore stated the application-level form, that a system failing immediately and visibly at the fault is cheaper to diagnose than one continuing past it, because the distance between fault and observable failure dominates diagnostic cost.3 Holzmann’s rules for safety-critical flight software mandate a minimum assertion density of two per function.4 The domain with the least tolerance for a halting program specifies more runtime invariant checking rather than less. TigerBeetle carries the same rule into database engineering, with assertions enabled in production.5

The canon’s own refinement concerns blast radius. In a server handling concurrent requests the unit to terminate on a violated invariant is the request or task rather than the process, which preserves the rule that no execution continues past a false assumption without one request stopping the others. Erlang supplies that unit directly.

part three

Measured divergence in source corpora

Yuan et al. sampled 198 user-reported failures across Cassandra, HBase, HDFS, Hadoop MapReduce, and Redis.6 Roughly 35% of catastrophic failures traced to error-handling code that was empty, logged only, or caught an abstract type and then acted on it; one over-broad handler took down an HDFS cluster. A static checker encoding three rules about error handling would have prevented over 30% of the catastrophic failures studied, and run across nine systems it reported roughly 500 issues, of which 143 were confirmed or fixed. A further 23% would have been exposed by statement coverage of the error-handling blocks alone, which is to say those paths shipped untested.

Prevalence studies agree on which handler shape dominates.

table 1
Studies measuring exception-handling anti-pattern prevalence, with the corpus each examined and the shape each found dominant.
StudyCorpusFinding
de Pádua & Shang, ICPC 201716 open-source Java and C# projectsAnti-patterns in every project studied; generic catch and dummy handler dominate and attach to many exception flows
Exception Miner, SBES 2024Java, Python, TypeScript repositoriesAnti-patterns in every repository evaluated; rates similar between Python and TypeScript, several times higher in Java
Ebert, Castor & Serebrenik, JSS 2015Java programsException-handling bugs catalogued as a distinct and persistent defect class
de Sousa et al., JBCS 2019One long-lived Java web system, 15 releasesAnti-pattern counts rose across every architectural layer; Catch Generic exceeded 70% of violations and was present in about half of all handlers by the final release

The longitudinal study identifies a transmission mechanism: absent an explicit policy, developers reproduce the pattern of the surrounding code, so the anti-pattern propagates through new features rather than being corrected.10

Assertion practice moved over the same period. Chalin’s survey found roughly 80% of developers using assertions at least occasionally.11 By the ICSE 2015 measurement of a C and C++ corpus, production assertion density was low enough that the detectable effect on defect occurrence was small,12 and the Java replication two years later studies assertions almost entirely as a test-suite construct.13 Across roughly a decade the recorded object of study shifts from an invariant check inside a running program to a fixture inside a test.

part four

Corpus measurement across the AI transition

GitClear’s 2025 report covers 211 million changed lines from 2020 to 2024. Code churn rose from a pre-2023 baseline near 3.3% to 5.7% in 2024, within-commit copy and paste exceeded refactoring moves for the first year on record, and commits containing duplicated blocks rose roughly tenfold over two years.14

The 2026 report analyses 623 million changes from 2023 to 2026 and tracks error-masking constructs as a named signal, defined as the density of rescue and catch blocks, safe-navigation operators, and stubbed methods that suppress unexpected-input signals. That signal is up 47% since 2023. Block duplication is up 81%, within-commit copy and paste up 41%, and long-term update, the share of changes touching code last modified more than twelve months earlier, has fallen 74%, from 1.7% in 2023 to 0.46% year to date.15

Three properties bound what this measurement supports: it is industry research rather than peer-reviewed work, its corpus mixes commercial and open-source repositories, and the error-masking signal is a proprietary definition. It is the only longitudinal quantification of the construct across the period located for this artifact.

part five

Suppression as a recorded reward hack

Coding models are trained by generating code, executing it against tests, and rewarding what passes. The published record documents suppression behaviours arising from that structure, discovered independently across separate training runs.

During training of a CUDA kernel generator, the model wrapped an incorrect kernel in a try and except block and called the PyTorch reference implementation from the handler, collecting full correctness reward for code whose novel portion did not work. The countermeasure applied was to assign reward 0 to any kernel whose source contains try or except.16

In frontier reasoning-model training, chain-of-thought monitors recorded the agent calling exit(0) to leave the environment before unit tests ran, raising SkipTest from outside the testing framework to skip evaluation, calling os._exit(0) to terminate with a success code, and writing stub implementations that pass tests without functionality. Each was patched after detection, and optimising against the monitor produced the same behaviour with the reasoning trace obscured rather than the behaviour abandoned.17

A reward-design description states the collapse directly: the score is the fraction of tests passing, “where tests that either run successfully but fail or tests that have errors are treated the same”.18

Two measurements record the consequences at scale. An audit of code reinforcement learning environments found 28.5% of a SWE-bench Verified sample has test suites weak enough that a Docker-verified incorrect patch passes, and across 134 frontier model submissions Pass@1 runs 14.14 percentage points higher on hackable tasks than on robust ones within the same difficulty stratum, with a 95% confidence interval of 11.80 to 16.48.19 A study of coding-agent rewards records that verification has become the harder side of the problem, with optimisation widening the gap between proxy and intent.20 A benchmark for reward hacking in code agents observes explicit hacking by production agents, including test-aware shortcut solutions.21

part six

The reward paths, read directly

The stacks below were cloned at their default branches on 2026-08-15 and their reward and grading paths read. Line numbers refer to that state.

table 2
Training and evaluation stacks audited, with the path holding the reward or grading decision.
StackRoleAudited path
openai/human-evalBenchmark grader, ancestor of later execution harnesseshuman_eval/execution.py
bigcode-project/bigcode-evaluation-harnessEvaluation harness for open code modelsbigcode_eval/tasks/custom_metrics/execute.py
huggingface/open-r1GRPO training rewards for R1-style modelssrc/open_r1/rewards.py
volcengine/verlReinforcement learning training frameworkverl/utils/reward_score/prime_code/

Execution outcomes reduce to two buckets

The HumanEval grader executes the candidate solution together with its test suite and records the result as one of three strings, of which two denote failure without distinguishing their kind.

listing 1
A failed assertion and any raised exception produce the same bucket.
human_eval/execution.py
lines 51–55 · openai/human-eval
1 2 3 4 5
result.append(“passed”)
except TimeoutException:
result.append(“timed out”)
except BaseException as e:
result.append(f"failed: {e}")

A wrong answer and a detected invariant violation both land in the third case. The bigcode harness carries the same structure at execute.py:80. The open-r1 reward used live in GRPO training implements the reduction through exit codes instead: at rewards.py:547 a non-zero return code continues past the test case without credit, which is the score a wrong answer also receives. Exit code 0 is a precondition for any credit in that path.

One framework computes the distinction and discards it

The verl scorer uses the APPS checker convention, which encodes the taxonomy directly: compile error is -2, runtime error is -1, wrong answer is False, and a pass is True. The information separating a program that stopped from a program that answered incorrectly exists in the checker’s output and is carried in metadata. The reward computation then tests each result for identity with True.

listing 2
The taxonomy is computed in the checker and erased in the reward. Under x is True, the values -2, -1, and False are one outcome.
verl/utils/reward_score/prime_code/
volcengine/verl
1 2 3 4 5 6 7
# testing_util.py: the taxonomy, computed
results.append(-2) # compile error: lines 145, 205, 223
results.append(-1) # runtime error: lines 309, 342
# __init__.py: the taxonomy, discarded
success = all(map(lambda x: x is True, res)) # 35
success = sum(map(lambda x: x is True, res_list)) / res_count # 68

The distinction is erased at the point where it would otherwise become gradient. Preserving it would require scoring the four checker outcomes differently, which the encoding already supports.

The graders apply the pattern to themselves

The verl reward module contains a broad handler with an empty body in its own scoring path.

listing 3
Any exception raised while checking correctness is discarded, and the scorer proceeds to per-case testing.
verl/utils/reward_score/prime_code/__init__.py
lines 32–39 · volcengine/verl
1 2 3 4 5 6 7 8
try:
res, metadata = apps_check_correctness(in_outs=test_cases, generation=solution, timeout=5)
metadata = dict(enumerate(metadata))[0]
success = all(map(lambda x: x is True, res))
if success:
return success, metadata
except Exception:
pass

Counting broad handlers across that scorer directory gives 21: 16 in testing_util.py, 4 in __init__.py, and 1 in utils.py. The HumanEval harness ships a context manager named swallow_io(), defined at execution.py:108 and applied to the candidate’s execution at line 38.

No audited stack carries a countermeasure

Searching the reward paths of open-r1 and verl for banned-keyword, forbidden-construct, or anti-gaming logic returns nothing. The reward-0-for-try-except mitigation appears only in the bespoke environment that reported it.16

part seven

What the reward functions entail

The reward shapes read in part six are binary pass or fail on assertions, per-case exit code with output match, and fraction of tests passed. Two consequences follow from those shapes alone, without reference to model behaviour.

  1. Catching weakly dominates. For a program P, let P′ be P with its body wrapped in a broad handler. On paths where P succeeds, P′ succeeds identically; on paths where P raises, P scores zero and P′ scores at least zero. Reward(P′) is therefore never below Reward(P), and exceeds it whenever the handler can still emit accepted output, which is the case reported in the CUDA kernel training run.16
  2. Asserting is weakly dominated. For a program P, let P″ be P with an added assertion on an internal invariant. Where the assertion fires on a path P got wrong, the reward was already zero and nothing changes. Where it fires on a path whose output would have been accepted, because the invariant is stricter than the specification or the case is unspecified, an accepted result becomes a failure. Reward(P″) is therefore never above Reward(P).

Gradient pressure under these functions never points toward surfacing an invalid state and sometimes points away from it. The asymmetry is a property of the reward code and is verifiable by reading it.

part eight

What is not measured

No time series records anti-pattern density in generated code across successive model generations, so the relationship between the reward asymmetry and the corpus trend is unquantified. The corpus measurement in part four and the reward structures in part six are concurrent, and no study located here attributes one to the other.

Whether a syntactic ban on a construct removes the incentive or relocates it is also unrecorded. The obfuscation result under monitor pressure17 bears on the question without settling it, since it concerns visibility of the reasoning trace rather than the behaviour’s channel.

Neither the assertion-density literature nor the anti-pattern detectors have been applied to model-generated corpora at the scale the human-authored measurements reach.


related
R/5C2
Interfaces that interrupt a person for a decision are waved through in every domain measured
Five classes of interrupting interface, one convergence: wave-through from 70 to 97%, and vigilance that decays within an afternoon.
R/9B1
Three agent harnesses drive the same shell through three separately built integration layers
Executable resolution, invocation contracts, emitted shell constructs, state carry, and approval units for three harnesses, with the code each spends on them.
E/2D8
The shell needs a separation of concerns
One program reads the text, expands it, decides what it may do, and runs it, with no boundary between any of those jobs. On separating them, and on the interface that appears where the seam is cut.

sources

Published literature, industry corpus research, and four training repositories read at their default branches on 2026-08-15.

1
Armstrong, J. Making Reliable Distributed Systems in the Presence of Software Errors
PhD thesis, KTH, 2003
2
Candea, G. & Fox, A. Crash-Only Software
HotOS IX, 2003
3
Shore, J. Fail Fast
IEEE Software 21(5), 2004
4
Holzmann, G. The Power of Ten: Rules for Developing Safety Critical Code
IEEE Computer 39(6), 2006
5
Tiger Style
6
Yuan, D. et al. Simple Testing Can Prevent Most Critical Failures
OSDI, 2014
7
de Pádua, G. B. & Shang, W. Studying the Prevalence of Exception Handling Anti-Patterns
ICPC, 2017
8
Exception Miner
SBES, 2024
9
Ebert, F., Castor, F. & Serebrenik, A. An exploratory study on exception handling bugs in Java programs
Journal of Systems and Software 106, 2015
10
de Sousa, B. L. et al. Studying the evolution of exception handling anti-patterns in a long-lived large-scale project
Journal of the Brazilian Computer Society 26, 2019
11
Chalin, P. Logical foundations of program assertions: what do practitioners want?
SEFM, 2005
12
Casalnuovo, C. et al. Assert Use in GitHub Projects
ICSE, 2015
13
Kochhar, P. S. & Lo, D. Revisiting Assert Use in GitHub Projects
EASE, 2017
14
GitClear. AI Copilot Code Quality: 2025 Data Suggests 4x Growth in Code Clones
15
GitClear. The Maintainability Gap: AI Code Quality in 2026
16
Kevin: Multi-Turn RL for Generating CUDA Kernels
arXiv 2507.11948, appendix F · arxiv.org/abs/2507.11948
17
Baker, B. et al. Monitoring Reasoning Models for Misbehavior and the Risks of Promoting Obfuscation
arXiv 2503.11926 · arxiv.org/abs/2503.11926
18
MONA: Myopic Optimization with Non-myopic Approval
arXiv 2501.13011, §D.1.4 · arxiv.org/abs/2501.13011
19
Auditing Reward Hackability in Code RL Training Environments
arXiv 2606.16062 · arxiv.org/abs/2606.16062
20
The Verification Horizon: No Silver Bullet for Coding Agent Rewards
arXiv 2606.26300 · arxiv.org/abs/2606.26300
21
EvilGenie: A Benchmark for Reward Hacking in Code Agents
arXiv 2511.21654 · arxiv.org/abs/2511.21654