Bug: cora review exits with code 2 despite producing valid SARIF with no blocking findings
Summary
cora review (v0.4.0) exits with code 2 even when the review completes successfully and the SARIF output contains zero error-level findings. This causes the cora-review-action GitHub job to fail, even though the review itself found no issues.
This blocks PR merges when "Cora Review" is configured as a required status check in branch protection rules.
Environment
- cora-cli version: v0.4.0 (latest at time of writing)
- cora-review-action:
codecoradev/cora-review-action@v1
- Runner:
ubuntu-latest
- Project:
codecoradev/rungu (Rust workspace, 6 crates)
- Config: project-level
.cora.yaml with profile: rust-strict
Reproduction
Two PRs reviewed in the same CI pipeline, same project, same config:
| PR |
Diff size |
Files changed |
Cora Review result |
cora exit code |
| #13 |
+255 / -22 |
7 |
✅ pass |
0 |
| #14 |
+494 / -3 |
5 |
❌ fail |
2 |
Key observation: PR #14 has a larger diff (~2x). The Cora AI review comment on both PRs says:
✅ No issues found. Code looks good!
Yet PR #14's job fails with exit code 2.
Evidence
1. Cora AI review comment on PR #14
The review comment (posted by actions/github-script step):
## 🔍 Cora AI Code Review
✅ **No issues found. Code looks good!**
2. SARIF analysis — "No blocking issues"
The Check SARIF for findings step in cora-review-action runs:
errors = [r for r in results if r.get('level') == 'error']
print(len(errors))
Output: No blocking issues. — 0 error-level findings in the SARIF.
3. Timeline from CI logs (PR #14, run 27557790644, job 81461315657)
15:38:42.227 Using project .cora.yaml for configuration
15:38:56.172 ##[error]Process completed with exit code 2.
15:38:57.469 echo "No blocking issues."
15:38:57.589 No blocking issues.
The cora review command runs for ~14 seconds, exits with code 2, but produces valid SARIF output (>10 bytes). The action's retry logic accepts this (because SARIF_BYTES > 10), so downstream steps proceed normally. However, the step itself has already failed because GitHub Actions shells run with set -o pipefail by default.
4. Comparison with PR #13 (passing)
PR #13 has a smaller diff (+255/-22) and cora review exits with code 0. Same project, same .cora.yaml, same action version. The only variable is diff size (~2x).
Root cause hypothesis
cora review produces valid SARIF with 0 error-level findings and a "No issues found" comment, but returns exit code 2 instead of 0. Possible causes:
- A partial failure in the LLM review pipeline (e.g., one diff chunk failed to process, but overall review completed gracefully)
- An exit code mapping bug (exit 2 might mean "warnings found" internally, but should be 0 when
--severity major finds nothing at or above threshold)
- A timeout or rate limit on larger diffs that degrades gracefully (produces output) but still returns non-zero
- Diff chunking: larger diffs may be split into chunks; if one chunk's LLM call fails but others succeed, the overall exit code might reflect the partial failure
Expected behavior
cora review should exit 0 when:
- The review completed (SARIF was produced)
- The
--severity filter results in no findings at or above the specified threshold
- The PR comment says "No issues found"
If there are internal warnings or partial failures, they should be:
- Logged to stderr (already happening)
- Reflected in SARIF as
level: warning (already happening)
- Not cause a non-zero exit code unless the review itself failed to produce valid output
Suggested exit code semantics
| Code |
Meaning |
| 0 |
Review completed, no findings at or above --severity threshold |
| 1 |
Review completed, findings at or above threshold (blocking) |
| 2 |
Review failed — no valid output produced (API error, timeout, etc.) |
Currently, exit 2 is returned even when output IS produced and NO blocking findings exist.
Impact
- PRs with larger diffs are consistently blocked from merging when "Cora Review" is a required check
- Requires manual intervention (temporary branch protection bypass) to merge
- Undermines trust in CI — a "failing" check that actually found no issues
Related
Bug:
cora reviewexits with code 2 despite producing valid SARIF with no blocking findingsSummary
cora review(v0.4.0) exits with code 2 even when the review completes successfully and the SARIF output contains zero error-level findings. This causes thecora-review-actionGitHub job to fail, even though the review itself found no issues.This blocks PR merges when "Cora Review" is configured as a required status check in branch protection rules.
Environment
codecoradev/cora-review-action@v1ubuntu-latestcodecoradev/rungu(Rust workspace, 6 crates).cora.yamlwithprofile: rust-strictReproduction
Two PRs reviewed in the same CI pipeline, same project, same config:
Key observation: PR #14 has a larger diff (~2x). The Cora AI review comment on both PRs says:
Yet PR #14's job fails with exit code 2.
Evidence
1. Cora AI review comment on PR #14
The review comment (posted by
actions/github-scriptstep):2. SARIF analysis — "No blocking issues"
The
Check SARIF for findingsstep incora-review-actionruns:Output:
No blocking issues.— 0 error-level findings in the SARIF.3. Timeline from CI logs (PR #14, run 27557790644, job 81461315657)
The
cora reviewcommand runs for ~14 seconds, exits with code 2, but produces valid SARIF output (>10 bytes). The action's retry logic accepts this (becauseSARIF_BYTES > 10), so downstream steps proceed normally. However, the step itself has already failed because GitHub Actions shells run withset -o pipefailby default.4. Comparison with PR #13 (passing)
PR #13 has a smaller diff (+255/-22) and
cora reviewexits with code 0. Same project, same.cora.yaml, same action version. The only variable is diff size (~2x).Root cause hypothesis
cora reviewproduces valid SARIF with 0 error-level findings and a "No issues found" comment, but returns exit code 2 instead of 0. Possible causes:--severity majorfinds nothing at or above threshold)Expected behavior
cora reviewshould exit 0 when:--severityfilter results in no findings at or above the specified thresholdIf there are internal warnings or partial failures, they should be:
level: warning(already happening)Suggested exit code semantics
--severitythresholdCurrently, exit 2 is returned even when output IS produced and NO blocking findings exist.
Impact
Related