Exception Contract Drift Signal (ECM)¶
Signal ID: ECM
Full name: Exception Contract Drift
Type: Scoring signal (contributes to drift score)
Default weight: 0.03
Scope: git_dependent
What ECM detects¶
ECM detects public functions whose exception profile changed across recent commits while the function signature remained stable. When a function silently starts raising different exceptions (or stops raising ones it used to), callers break without any API change being visible.
Example finding¶
exception_contract_drift in services/payment.py::process_payment
Previous exceptions: [ValueError, PaymentError]
Current exceptions: [ValueError, PaymentError, TimeoutError, ConnectionError]
Signature: unchanged
→ New exceptions: TimeoutError, ConnectionError (added in commit abc123)
The function now raises two new exceptions that callers don't handle.
Why exception contract drift matters¶
- Silent API breakage — the function signature doesn't change, but callers start seeing unexpected exceptions.
- AI-generated changes often modify exception paths without updating call sites.
- Cascading failures — new exceptions propagate through the call chain, causing crashes in unrelated code.
- Testing blind spots — tests written for the original exception profile miss the new ones.
How the score is calculated¶
ECM compares exception profiles across git history:
- Extract current exception profile — all
raisestatements and their exception types from AST. - Extract previous exception profile — same analysis on the last committed version.
- Compute difference — new exceptions, removed exceptions, changed exception patterns.
- Score based on delta magnitude — more changes = higher score.
Severity thresholds:
| Score range | Severity |
|---|---|
| ≥ 0.7 | HIGH |
| ≥ 0.5 | MEDIUM |
| ≥ 0.3 | LOW |
| < 0.3 | INFO |
How to fix ECM findings¶
- Document the new exceptions — add them to the docstring's Raises section.
- Update callers — ensure all call sites handle the new exceptions.
- Consider wrapping — if the new exceptions come from a dependency, wrap them in a domain-specific exception.
- Add tests — write tests that verify both the old and new exception paths.
Configuration¶
Detection details¶
- Load git history for modified files.
- Parse current AST and previous AST (from last commit).
- Extract exception profiles —
raisestatements, exception types, handler patterns. - Diff profiles — identify added, removed, changed exceptions.
- Score delta per function.
ECM requires git history (git_dependent=True). Without a git repository, ECM produces no findings.
Related signals¶
- BEM (Broad Exception Monoculture) — detects poor exception quality. ECM detects exception changes over time.
- TVS (Temporal Volatility) — detects volatile modules. ECM detects specific behavioral changes in exception handling.
- CCC (Co-Change Coupling) — also git-dependent. ECM focuses on exception-specific drift.