The Retry Loop That Swallowed the Reason
bare except: pass hides the real failure
Published Oct 29, 2026
Executive Summary
A vibe-coded payment retry loop wraps the charge in bare except: pass. It never crashes — but it also never learns why the charge failed. A one-character typo and a gateway outage produce the same silent outcome: three attempts, then None, with nothing logged.
The Prompt
“Add error handling around the payment retry loop so it never crashes.”
The Flaw
bare except: pass swallows every exception — the real gateway error, but also typos, AttributeErrors, and KeyboardInterrupt. The loop never crashes, but it also never learns why the charge failed: a coding bug is indistinguishable from a provider outage. After three attempts it returns None, and the order silently fails with nothing in the logs to diagnose it.
Risk & Impact
[Correctness] Payments fail silently. A one-character typo in gateway.charge produces the same outcome as a provider outage — and there is no log to tell them apart.
Cost: Undiagnosable payment failures that only surface as angry customers and unprocessed orders.
Code Comparison
❌ Vulnerable (AI generated)
❌ Vulnerable (AI generated)
✅ Hardened (production ready)
The Fix
Catch the specific, retryable exception type — log it — and raise loudly when retries are exhausted. Never bare except, never pass.
Prevention
- [linter] flake8-bugbear (B001) and pylint (W0702/W0703) flag bare except and except: pass.
- [ci] A test that raises a non-transient error must NOT be retried and must raise — proving the loop only retries what it should.
- [manual] Define the failure mode for each except clause (rule 2): what is retryable, what is fatal, and where the log goes.
Why This Happened
Root cause: the prompt omitted Rule 2 — the guardrails that would have caught this. See the full guide →
