Skip to content

bug: cora review exits code 2 despite valid SARIF and zero blocking findings (larger diffs) #312

Description

@ajianaz

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:

  1. The review completed (SARIF was produced)
  2. The --severity filter results in no findings at or above the specified threshold
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions