Skip to content

Fix: Python TypeError: missing required positional argument

FixDevs · (Updated: )

Part of:  Python Errors

Quick Answer

How to fix Python TypeError missing required positional argument caused by missing self, wrong argument count, class instantiation errors, and decorator issues.

TypeError: missing required positional argument

Nine times out of ten when I hit this error it was self: I had called a method on the class itself instead of on an instance, and Python quietly slid my first real argument into the self slot. The count in the message is from Python’s point of view, not mine, which is why the number so often looks off by one. I learned to read the parameter name it reports before anything else, self means “you forgot to instantiate, or you typed Class.method where you meant instance.method”, and a real parameter name means “you genuinely left one out”. In my experience that single distinction resolves most of these in seconds.

You call a function or method and get:

TypeError: __init__() missing 1 required positional argument: 'name'

Or variations:

TypeError: greet() missing 1 required positional argument: 'name'
TypeError: process_data() missing 2 required positional arguments: 'data' and 'format'
TypeError: send_email() missing 1 required positional argument: 'self'

Python called a function or method but did not receive all the arguments it requires. The function expects more arguments than were provided.

Where the Missing Argument Goes

Python functions have a fixed set of required parameters (those without default values). When you call a function without providing all required arguments, Python raises TypeError before the function body even executes. The signature check happens in the CPython interpreter’s argument-binding step, so the error is raised even if the function body would have crashed for another reason.

Method calls add a second layer of confusion. When you write instance.method(arg), Python turns it into ClassName.method(instance, arg) under the hood, self is the first positional argument, supplied implicitly by the descriptor protocol. When you write ClassName.method(arg), Python does not supply self, so your arg lands in the self slot and the next parameter is missing. The error message says missing 1 required positional argument: 'self' or 'name' depending on whether you also forgot to instantiate the class.

A note on Python versions: since Python 3.10, these messages include the qualified name, so a method error reads User.greet() missing 1 required positional argument: 'self' and a constructor reads User.__init__() missing 1 required positional argument: 'name'. Python 3.9 and earlier printed just greet() and __init__(). Plain module-level functions still show only their bare name on every version, since their qualified name has no class prefix. The examples below use the short form; the diagnosis is identical either way.

A third source is signature mismatch across boundaries: callback functions passed to map, filter, sorted, threading.Thread, an async framework, or a decorator may be called with a different argument count than you intended. Python does not check the signature at registration time; it discovers the mismatch only when the callback fires. This is why this error frequently surfaces only in production code paths that tests did not exercise.

Common causes:

  • Missing self error. You called an instance method on the class itself instead of on an instance.
  • Wrong number of arguments. You forgot to pass one or more required arguments.
  • Missing parentheses. You referenced the class instead of instantiating it.
  • Decorator issue. A decorator consumed an argument or changed the function signature.
  • Callback signature mismatch. A callback function expects more arguments than the caller provides.
  • Refactored function. The function signature changed but not all call sites were updated.
  • Async vs sync mismatch. An async function called without await returns a coroutine that you then try to invoke as if it were the real callable.

In Production: Incident Lens

TypeError: missing required argument is the canonical “this slipped past tests” production error. The function compiles, the import succeeds, the application starts cleanly, and then the first user request that exercises the affected code path returns a 500. Unlike ImportError or SyntaxError, this only triggers when the broken call site is actually invoked, so it can lurk in cold paths (admin endpoints, scheduled jobs, error handlers) for weeks.

How it surfaces: an alert from Sentry, Rollbar, or your logging stack shows a spike of TypeError: foo() missing 1 required positional argument: 'bar'. The stack trace points at the call site. The triggering request is usually identifiable from the breadcrumb trail, often a payload variant or an endpoint that tests did not cover. In Django this manifests as a 500 with the error in traceback.format_exc() in the logs; in FastAPI it becomes a Internal Server Error JSON response and a logged exception.

Blast radius: scoped to the specific code path. If the error lives in a request handler, every request that reaches that handler fails. If it lives in a background task, the task fails and (depending on the framework) gets retried, which may amplify the error rate. If it lives in an error handler itself, you get a secondary failure that masks the original, debugging gets harder because the visible exception is from the handler, not the cause.

Monitoring signal: the high-signal alerts come from your APM (Sentry, Datadog APM, New Relic). Alert on new exception types appearing within 5 minutes of a deploy and on any TypeError whose count crosses a deploy boundary. Pair this with endpoint-level error rate monitoring, if /api/admin/export jumps from 0 to 5% error rate in the minute after a deploy, you have your culprit. Sentry’s release tracking attributes the regression to the exact commit, which is the data you actually want at 3am.

Recovery sequence: rollback first, debug second. The error is deterministic for the affected code path, so leaving the broken version running just generates more noise without giving you new information. Roll the deploy back, confirm the error rate returns to baseline, then reproduce the call locally with the same payload that triggered the production failure. Add the missing kwarg (or restore the deleted parameter), write a test that hits the endpoint with that payload, and ship the fix in a follow-up PR.

Postmortem preventive: the durable fix is type checking and integration tests, not stricter code review. Run mypy --strict (or at minimum --disallow-untyped-defs and --check-untyped-defs) in CI so that signature changes are flagged at the type-checker level before they reach review. Add an integration test for every public endpoint that posts a realistic payload, fixture-based tests with the real JSON your API receives catch this class of bug reliably. For background jobs and rare code paths, schedule a synthetic invocation in a staging-like environment so the cold path runs at least once per day with the new code.

Fix 1: Fix the “missing self” Error

The most common case. If the error says missing 1 required positional argument: 'self', you called a method on the class instead of an instance:

Broken:

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

    def greet(self):
        return f"Hello, {self.name}!"

# Calling on the class (wrong):
User.greet()  # TypeError: greet() missing 1 required positional argument: 'self'

Fixed, create an instance first:

user = User("Alice")
user.greet()  # "Hello, Alice!"

When you call user.greet(), Python automatically passes user as self. When you call User.greet(), there is no instance to pass as self, so it is missing.

Broken, forgot to instantiate:

class Database:
    def __init__(self, url):
        self.url = url

    def connect(self):
        print(f"Connecting to {self.url}")

# Missing parentheses — Database is the class, not an instance:
db = Database
db.connect()  # TypeError: connect() missing 1 required positional argument: 'self'

Fixed:

db = Database("postgresql://localhost/mydb")
db.connect()  # Works

Whenever the missing name is self, the fix is almost always to change ClassName.method() into instance.method(). You never pass self yourself, Python supplies it automatically when you call a method on an instance, so seeing self in the message is really Python telling you there was no instance in the call at all.

Fix 2: Pass All Required Arguments

Check the function signature and provide every argument that does not have a default value:

def send_email(to, subject, body):
    print(f"Sending to {to}: {subject}")

# Missing arguments:
send_email("alice@example.com")
# TypeError: send_email() missing 2 required positional arguments: 'subject' and 'body'

# Fixed — pass all arguments:
send_email("alice@example.com", "Hello", "How are you?")

Use keyword arguments for clarity:

send_email(
    to="alice@example.com",
    subject="Hello",
    body="How are you?"
)

Add default values for optional parameters:

def send_email(to, subject="No Subject", body=""):
    print(f"Sending to {to}: {subject}")

# Now only 'to' is required:
send_email("alice@example.com")  # Works

Fix 3: Fix init Arguments

When creating instances, the error tells you what argument __init__ expects:

class Config:
    def __init__(self, filepath, encoding="utf-8"):
        self.filepath = filepath
        self.encoding = encoding

# Missing filepath:
config = Config()
# TypeError: __init__() missing 1 required positional argument: 'filepath'

# Fixed:
config = Config("config.yaml")
config = Config(filepath="config.yaml", encoding="latin-1")

Common in Django models:

# Django model
class Article(models.Model):
    title = models.CharField(max_length=200)

# Creating without required field:
article = Article()
article.save()
# IntegrityError or TypeError depending on validation

For Django database errors, see Fix: Django OperationalError: no such table.

Fix 4: Fix Static and Class Methods

If a method does not need self, declare it as @staticmethod or @classmethod:

Broken, method does not use self but still requires it:

class MathHelper:
    def add(a, b):  # Missing 'self' parameter
        return a + b

helper = MathHelper()
helper.add(2, 3)
# TypeError: add() takes 2 positional arguments but 3 were given
# (Python passed 'self' as the first argument, shifting a and b)

Fixed, use @staticmethod:

class MathHelper:
    @staticmethod
    def add(a, b):
        return a + b

MathHelper.add(2, 3)  # Works — no self needed
helper = MathHelper()
helper.add(2, 3)       # Also works

Fixed, use @classmethod if you need the class:

class Config:
    default_path = "/etc/config.yaml"

    @classmethod
    def from_default(cls):
        return cls(cls.default_path)

    def __init__(self, path):
        self.path = path

config = Config.from_default()  # Works — cls is passed automatically

Fix 5: Fix Callback and Lambda Arguments

When passing functions as callbacks, the callback signature must match what the caller expects:

Broken, callback expects more arguments than provided:

def on_complete(result, status):
    print(f"Done: {result} ({status})")

# The caller only passes one argument:
results = [1, 2, 3]
list(map(on_complete, results))
# TypeError: on_complete() missing 1 required positional argument: 'status'

Fixed, match the expected signature:

def on_complete(result):
    print(f"Done: {result}")

list(map(on_complete, results))

Or provide defaults:

def on_complete(result, status="success"):
    print(f"Done: {result} ({status})")

list(map(on_complete, results))  # Works — status defaults to "success"

Broken, sorted() key function with wrong signature:

def compare(a, b):
    return a - b

# sorted() key takes one argument, not two:
sorted([3, 1, 2], key=compare)
# TypeError: compare() missing 1 required positional argument: 'b'

Fixed:

sorted([3, 1, 2], key=lambda x: x)  # Key takes one argument

Fix 6: Fix Decorator Issues

Decorators can change how arguments are passed:

Broken, decorator that does not pass arguments through:

def my_decorator(func):
    def wrapper():  # Missing *args, **kwargs!
        print("Before")
        func()      # Missing arguments!
        print("After")
    return wrapper

@my_decorator
def greet(name):
    print(f"Hello, {name}")

greet("Alice")
# TypeError: wrapper() takes 0 positional arguments but 1 was given

Fixed:

def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("Before")
        result = func(*args, **kwargs)
        print("After")
        return result
    return wrapper

@my_decorator
def greet(name):
    print(f"Hello, {name}")

greet("Alice")  # Works

Always use *args, **kwargs in decorator wrappers to forward all arguments.

A decorator that works fine on zero-argument functions and then breaks the moment it wraps one with arguments is a classic version of this bug. Always give the wrapper *args, **kwargs, and add functools.wraps so the wrapped function keeps its own name and docstring instead of reporting as wrapper:

from functools import wraps

def my_decorator(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs)
    return wrapper

Fix 7: Fix Inheritance and super() Calls

When overriding methods in subclasses, make sure you pass the required arguments to super():

Broken:

class Animal:
    def __init__(self, name, species):
        self.name = name
        self.species = species

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)  # Missing 'species'!
        # TypeError: __init__() missing 1 required positional argument: 'species'

Fixed:

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name, "Dog")

Fix 8: Debug the Error

When the error is not obvious, inspect the function signature:

import inspect

# See the function signature:
print(inspect.signature(my_function))

# See all parameters:
for name, param in inspect.signature(my_function).parameters.items():
    print(f"{name}: {param.kind.name}, default={param.default}")

This shows you exactly which parameters are required and which have defaults.

Use IDE features:

Most IDEs (VS Code, PyCharm) show function signatures as you type. Hover over the function name to see the expected arguments.

Check for method vs function:

print(type(obj.method))    # <class 'method'> — self is passed automatically
print(type(MyClass.method)) # <class 'function'> — self must be passed manually

If you see function where you expect method, you are calling it on the class instead of an instance.

Less Obvious Causes

If you have checked all the fixes above:

Check for __init__ in metaclasses or __new__. If the class uses a custom metaclass or overrides __new__, the error might originate there instead of __init__.

Check for property setters. A @property setter must accept exactly one value argument:

class Config:
    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):  # Must have 'value'
        self._name = value

Check for **kwargs masking a typo. When a subclass forwards **kwargs to a base class that quietly accepts anything, a misspelled keyword is swallowed instead of rejected, and the real argument shows up as missing, which sends you debugging the wrong line:

class Base:
    def __init__(self, **kwargs):
        pass  # silently accepts and ignores anything

class Child(Base):
    def __init__(self, name, **kwargs):
        super().__init__(**kwargs)  # forwards leftovers to Base
        self.name = name

# Typo: 'naem' instead of 'name'
Child(naem="Alice")
# TypeError: Child.__init__() missing 1 required positional argument: 'name'
# The misspelled 'naem' was forwarded to Base and dropped, so the error
# blames the missing 'name' rather than the typo that caused it.

The fix is to drop the unnecessary **kwargs from the subclass so a wrong keyword raises unexpected keyword argument immediately, or to validate the keys explicitly.

Check for circular imports. If a circular import causes a module to be partially loaded, classes or functions might be None or incomplete, leading to unexpected TypeError. See Fix: Python ImportError: circular import.

Check for Python version differences. Some functions changed their signatures between Python versions. For example, collections.OrderedDict.move_to_end() was added in Python 3.2. Check the Python docs for your version. If Python itself is not found, see Fix: python command not found.

Check for forgotten await on async functions. Calling an async def function without await returns a coroutine object, not the result. If you then try to pass that coroutine to something that expects the actual return value, the argument count looks right but the runtime call fails with the missing-argument variant when the coroutine is later awaited with the wrong args. See Fix: Python async/sync mix for the broader pattern.

Check for keyword-only argument requirements. A parameter declared after * in the signature is keyword-only: def func(a, *, b). Calling func(1, 2) raises TypeError: func() takes 1 positional argument but 2 were given and func(1) raises missing 1 required keyword-only argument: 'b'. Library authors increasingly use keyword-only arguments for clarity, especially in Python 3.10+.

Check for partial and partialmethod binding. functools.partial(func, arg) fixes arg as the first positional argument. If you later call the result, your supplied args shift right, and a method already bound to self then receives your arg as the second positional, leaving the next slot empty. Inspect with inspect.signature(partial_func) to see the post-binding signature.

Check for Pydantic and dataclass field changes. Adding a required field to a Pydantic model or dataclass without a default value breaks every existing instantiation. Use Field(default=...) or migrate existing call sites in the same commit.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles