mutated × shared — the answer changes between runs

Pool-Exhaustion Heisenbug

Whether a request succeeds or stalls depends on how many others hold the pool right now -- so the same call passes alone and fails under load.

01the recipe

In the wild

example.py
# SMELL: a short pool + a per-call timeout -> success depends on live load.
# (resource contention x time/money/entropy)
pool = ConnectionPool(size=4)
def handler(req):
    conn = pool.acquire(timeout=0.2)   # under load: sometimes returns None
    return conn.query(req.sql)         # ...then AttributeError, only sometimes

# RIGHT: size for peak, fail explicitly, never act on a missed acquire.
def handler(req):
    conn = pool.acquire(timeout=2.0)
    if conn is None:
        raise ServiceBusy()            # deterministic, observable backpressure
    try:
        return conn.query(req.sql)
    finally:
        pool.release(conn)
With a pool smaller than peak concurrency, whether you get a connection depends on how many requests happen to overlap with yours -- pure timing. It passes alone and fails only in the demo under load. Size for peak and turn a missed acquire into explicit backpressure, not a silent None.
// observed
contended: intermittent None -> AttributeError under concurrency
right: explicit ServiceBusy; outcome no longer depends on who else is in flight
02weakness catalog

Mapped weaknesses (CWE)

On its own, this defect is catalogued by MITRE as one or more of these weaknesses. The exploitable vulnerability usually appears only when it chains or combines with another.