PythonMastery
reference 3 min read · lesson 46 of 60 in Errors

TypeError: missing 1 required positional argument

1 · The lesson

read

What this error means

You called a function with fewer arguments than its def line asks for. Python matched what you passed against the parameters from left to right, ran out of values, and found a parameter with no default still waiting. It names that parameter for you, which is the most useful part of the message — read the name in quotes first.

When you see it

python
Traceback (most recent call last):
  File "main.py", line 6, in <module>
    print(order.total())
          ~~~~~~~~~~~^^
TypeError: Order.total() missing 1 required positional argument: 'tax'
python
Traceback (most recent call last):
  File "main.py", line 6, in <module>
    print(User.describe())
          ~~~~~~~~~~~~~^^
TypeError: User.describe() missing 1 required positional argument: 'self'

The second one is the tell-tale: when the missing argument is 'self', you called the method on the class, not on an object.

Why it happens

There are four common routes to it, and only the first is a plain typo.

1. You left an argument out. The function grew a parameter last week and one call site never got updated.
2. You called a method on the class. User.describe() has no object to hand over as self, so self is the thing missing.
3. You passed an argument that quietly became self. Order.total(0.2) binds 0.2 to self, so Python complains about tax — a parameter you thought you had supplied.
4. Something else calls your function for you. map(), sorted(key=...), a button callback or a thread passes exactly as many arguments as it decides, not as many as your function needs.

python
class Order:
    def __init__(self, subtotal):
        self.subtotal = subtotal

    def total(self, tax):
        return round(self.subtotal * (1 + tax), 2)

order = Order(120)
print(order.total())          # TypeError: Order.total() missing 1 required positional argument: 'tax'

How to fix it

Pass the argument, or give the parameter a default if leaving it out is genuinely normal:

python
class Order:
    def __init__(self, subtotal):
        self.subtotal = subtotal

    def total(self, tax=0.2):     # default VAT rate when the caller doesn't say
        return round(self.subtotal * (1 + tax), 2)

order = Order(120)
print(order.total())          # 144.0
print(order.total(0.05))      # 126.0

Only add a default when there really is a sensible one. A default that hides a forgotten argument turns a loud error into a quiet wrong invoice.

If the missing one is self, create an instance first:

python
class User:
    def __init__(self, name):
        self.name = name

    def describe(self):
        return f"{self.name} (active)"

ada = User("Ada")
print(ada.describe())         # Ada (active) — not User.describe()

If the method never touches self, it shouldn't be an instance method at all — make it a @staticmethod and calling it on the class becomes fine.

When a library calls your function, fill in the extra arguments yourself with functools.partial or a lambda:

python
from functools import partial

def apply_discount(price, rate):
    return round(price * (1 - rate), 2)

prices = [19.99, 45.00, 8.50]

# map() passes ONE argument per item, so `rate` would be missing.
ten_off = partial(apply_discount, rate=0.10)
print(list(map(ten_off, prices)))                    # [17.99, 40.5, 7.65]
print([apply_discount(p, 0.10) for p in prices])     # same thing, and arguably clearer

When you'd actually see this in real code

  • Adding a parameter to a widely used function and grepping for only half of the call sites. The traceback points at the caller you missed.
  • Writing sorted(orders, key=compare) where compare(a, b) is an old-style two-argument comparison. key= passes one item; wrap it with functools.cmp_to_key(compare).
  • A Tkinter or GUI callback defined as def on_save(self, event) but registered somewhere that passes nothing.
  • A pandas df.apply(fee, axis=1) where fee(row, rate) needs a rate: pass it with df.apply(fee, axis=1, args=(0.03,)).
  • Calling Invoice.from_row(row) when from_row was written as an instance method instead of a @classmethod.

See Also

Found this useful? Share it with a friend who’s learning Python.