How to Resolve "TypeError: Cannot Create a Consistent Method Resolution Order (MRO)" in Python
When working with multiple inheritance in Python, you may encounter the error TypeError: Cannot create a consistent method resolution order (MRO). This error means Python can't figure out a logical order in which to look up methods across your class hierarchy. In this guide, we'll explain what MRO is, why this error occurs, and walk through clear solutions with examples to fix it.
What Is Method Resolution Order (MRO)?
Method Resolution Order (MRO) is the order in which Python looks through a class's parent classes when searching for a method. When you call a method on an object, Python follows the MRO to determine which class's implementation to use.
Python uses the C3 linearization algorithm to compute the MRO. This algorithm guarantees that:
- A child class is always checked before its parents.
- The order of parent classes specified in the class definition is preserved.
- Each class appears only once in the MRO.
You can inspect any class's MRO using the __mro__ attribute or the mro() method:
class A:
pass
class B(A):
pass
print(B.__mro__)
Output:
(<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
When the C3 algorithm cannot find an order that satisfies all its rules, Python raises the MRO error instead of silently picking a potentially incorrect order.
Why Does This Error Occur?
The error occurs when Python's C3 linearization algorithm detects a contradiction in your inheritance hierarchy. The most common scenario is the diamond inheritance problem with an inconsistent class order.
The Diamond Inheritance Problem
❌ Wrong: Inconsistent inheritance order:
class A:
def method(self):
print("A")
class B(A):
def method(self):
print("B")
class C(A, B): # Problem: A comes before B, but B inherits from A
def method(self):
print("C")
Output:
TypeError: Cannot create a consistent method resolution order (MRO) for bases A, B
Why does this fail? Let's break down the contradiction:
C(A, B)tells Python: "CheckAbeforeB."- But
B(A)tells Python: "Bis a subclass ofA, soBshould be checked beforeA."
These two rules directly contradict each other, making it impossible for Python to build a consistent MRO.
Think of it this way: Python needs A before B (because of how you defined C) and B before A (because B is a child of A). Both can't be true at the same time.
Visualizing the Problem
A
/ \
/ \
B |
\ /
\ /
C ← C(A, B) contradicts B(A)
C inherits from both A and B, but B already inherits from A. Listing A before B in C's parent list creates the contradiction.
How to Fix the Error
Solution 1: Reorder the Parent Classes
The simplest fix is to put the more specific (child) class before the more general (parent) class in the inheritance list:
class A:
def method(self):
print("A")
class B(A):
def method(self):
print("B")
class C(B, A): # ✅ B (more specific) comes before A (more general)
def method(self):
print("C")
c = C()
c.method()
print(C.__mro__)
Output:
C
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
Now the MRO makes sense: C → B → A → object. There's no contradiction because B (a child of A) is checked before A.
When using multiple inheritance, always list child classes before their parent classes in the inheritance list. The order should go from most specific to most general.
Solution 2: Remove the Redundant Parent Class
If B already inherits from A, then C doesn't need to explicitly inherit from A and it gets A automatically through B:
❌ Redundant:
class A:
def method(self):
print("A")
class B(A):
def method(self):
print("B")
class C(A, B): # A is redundant and causes the error
pass
✅ Fixed: Remove the redundant parent:
class A:
def method(self):
print("A")
class B(A):
def method(self):
print("B")
class C(B): # Only inherit from B; A is included automatically
pass
c = C()
c.method()
print(C.__mro__)
Output:
B
(<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
Solution 3: Make the Base Classes Independent
If you truly need multiple inheritance and both parent classes should be independent, make sure they don't share a parent-child relationship:
❌ Wrong: B inherits from A, causing a conflict in C:
class A:
def a_method(self):
print("A")
class B(A): # B depends on A
def b_method(self):
print("B")
class C(A, B): # Conflict!
def c_method(self):
print("C")
✅ Fixed: Make A and B independent:
class A:
def a_method(self):
print("A")
class B: # B no longer inherits from A
def b_method(self):
print("B")
class C(A, B): # No conflict: A and B are independent
def c_method(self):
print("C")
c = C()
c.a_method()
c.b_method()
c.c_method()
print(C.__mro__)
Output:
A
B
C
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>)
Solution 4: Use Mixins for Shared Behavior
If you need to share behavior across multiple classes without creating inheritance conflicts, use the mixin pattern. Mixins are small, focused classes designed to be combined through multiple inheritance:
class SerializerMixin:
def serialize(self):
return str(self.__dict__)
class LoggerMixin:
def log(self, message):
print(f"[LOG] {message}")
class BaseModel:
def __init__(self, name):
self.name = name
class User(SerializerMixin, LoggerMixin, BaseModel):
def __init__(self, name, email):
super().__init__(name)
self.email = email
user = User("Alice", "alice@example.com")
print(user.serialize())
user.log("User created")
print(User.__mro__)
Output:
{'name': 'Alice', 'email': 'alice@example.com'}
[LOG] User created
(<class '__main__.User'>, <class '__main__.SerializerMixin'>, <class '__main__.LoggerMixin'>, <class '__main__.BaseModel'>, <class 'object'>)
Mixins work well because they are independent classes that don't inherit from each other, avoiding MRO conflicts entirely.
A More Complex Example
Here's a real-world-like scenario with a correct diamond inheritance pattern using super():
class Animal:
def __init__(self, name):
self.name = name
print(f"Animal.__init__({name})")
def speak(self):
return "..."
class Flyer(Animal):
def __init__(self, name):
super().__init__(name)
print(f"Flyer.__init__({name})")
def fly(self):
return f"{self.name} is flying"
class Swimmer(Animal):
def __init__(self, name):
super().__init__(name)
print(f"Swimmer.__init__({name})")
def swim(self):
return f"{self.name} is swimming"
# Duck inherits from both: order matters!
class Duck(Flyer, Swimmer): # ✅ Both Flyer and Swimmer inherit from Animal
def __init__(self, name):
super().__init__(name)
print(f"Duck.__init__({name})")
def speak(self):
return "Quack!"
duck = Duck("Donald")
print(duck.speak())
print(duck.fly())
print(duck.swim())
print(Duck.__mro__)
Output:
Animal.__init__(Donald)
Swimmer.__init__(Donald)
Flyer.__init__(Donald)
Duck.__init__(Donald)
Quack!
Donald is flying
Donald is swimming
(<class '__main__.Duck'>, <class '__main__.Flyer'>, <class '__main__.Swimmer'>, <class '__main__.Animal'>, <class 'object'>)
This works because Duck(Flyer, Swimmer) places sibling classes in a consistent order and both ultimately lead to Animal.
Quick Reference
| Problem | Solution |
|---|---|
C(A, B) where B inherits from A | Reorder to C(B, A): specific before general |
| Redundant parent in inheritance list | Remove the redundant parent: C(B) instead of C(A, B) |
| Two parents share a common ancestor | Ensure consistent ordering; use super() |
| Need shared behavior without conflicts | Use the mixin pattern with independent classes |
Conclusion
The TypeError: Cannot create a consistent method resolution order (MRO) error occurs when Python's C3 linearization algorithm finds contradictions in your class hierarchy.
The fix comes down to ensuring a consistent, logical order in your inheritance declarations: always list more specific (child) classes before more general (parent) classes, remove redundant parent classes from your inheritance list, and consider using independent mixins when you need to share behavior across unrelated classes.
When in doubt, inspect the __mro__ attribute to understand how Python resolves methods in your class hierarchy.