mutated × unstructured — blows up live on input you didn't expect

Stale API After Upgrade (AttributeError)

A mixin reaches for a method a dependency upgrade quietly renamed or removed.

01the recipe

In the wild

example.py
# SMELL: a mixin assumes a method a dependency upgrade renamed/removed.
# (macro / mixin misuse x version / library mismanagement)
class Audited(Base):
    def save(self):
        self.log_change()       # provided by Base... until v3 renamed it
        super().save()          # AttributeError the first time this path runs

# RIGHT: pin the contract and adapt at the seam, not deep in a mixin.
class Audited(Base):
    def save(self):
        getattr(self, "log_change", self._audit_fallback)()
        super().save()
A mixin reaches for an inherited method a library upgrade quietly dropped; nothing fails at import, only when that path executes after deploy. It relies on behavior the new version no longer guarantees.
// observed
bug:   AttributeError: 'Audited' object has no attribute 'log_change'
right: missing hook degrades to a fallback, not a crash
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.