← Python Code Python's Hidden Traps
Browse Python Concepts

Exception Swallowing — How Bugs Disappear Silently

Mental Model

A bare 'except:' block is like a black hole: it silently absorbs everything that comes its way without any indication. Instead, explicitly catching 'Exception' or more specific types is like a filter, allowing you to selectively handle what you intend while letting critical signals pass through.

Rule: Never use a bare except clause or catch BaseException; instead, explicitly catch Exception or targeted subclasses.

The Setup

You are writing a long-running batch processing daemon that imports user data. You want to make it resilient, so you wrap the processing loop in a broad try-except block to make sure that any malformed record is bypassed and the daemon keeps running.

What Does This Print?

Broken code
Python
import sys
import time

def process_loop():
    for i in range(5):
        try:
            if i == 2:
                # Simulating a shutdown signal or sudden interrupt
                sys.exit(1)
            time.sleep(0.1)
        except:
            # Swallowing everything to keep the loop running
            pass
    print("Daemon finished successfully")

process_loop()
Predict what happens when the loop index reaches 2. Does the process exit immediately, or does it print the completion message?

The Output

What actually happens
Daemon finished successfully

The bare except: block successfully intercepted the SystemExit exception raised by sys.exit(1), completely ignored it, and allowed the function to terminate normally as if no error occurred. This prevents external orchestrators (like Kubernetes) from signaling the process to stop.

Why Python Does This

In Python, exceptions are hierarchical. The top of the hierarchy is BaseException. A bare except: statement is syntactic sugar for except BaseException:. This class sits above Exception and contains system-level interrupts like SystemExit, KeyboardInterrupt, and GeneratorExit. Catching BaseException or using bare except: intercepts these vital control flow signals, preventing developers from stopping the script via Ctrl+C and blocking container orchestration runtimes.

The Fix

Corrected pattern
Python
import sys

def process_loop():
    for i in range(5):
        try:
            if i == 2:
                sys.exit(1)
        # Target only standard operational exceptions, leaving system interrupts untouched
        except Exception as e:
            print(f"Log and handle expected operational error: {e}")

process_loop()

Explicitly catching 'Exception' (or more specific subclasses) ensures that only standard application errors are handled, allowing critical system-level exceptions like SystemExit or KeyboardInterrupt to propagate. This preserves Python's mechanisms for graceful shutdown and interrupt handling.

How This Fails in Real Systems

A background billing worker processed payment batches in an infinite loop inside a Kubernetes pod. A developer used a bare except block to bypass failed database rows. When the platform team rolled out a cluster upgrade, Kubernetes sent a SIGTERM (which raised SystemExit). The worker swallowed the exit signal, kept processing, and was forcibly killed via SIGKILL, corrupting active transaction logs.

Key Takeaway

Never use a bare except clause or catch BaseException; instead, explicitly catch Exception or targeted subclasses.
Common mistake: Developers use a bare 'except:' block, intending to catch only "errors" but inadvertently capturing critical system exceptions like SystemExit or KeyboardInterrupt, masking serious issues.