TypeError: takes 1 positional argument but 2 were given (tested fix)
TypeError: f() takes 1 positional argument but 2 were given means the call passed more positional arguments than the function accepts. For a method, the hidden extra argument is usually the instance, because self is missing. We reproduced 5 causes in Python 3.13 and tested each fix.
1. A method is missing self
This is the most common cause. Calling g.greet("Ann") passes the instance as the first argument, so Python counts one more argument than you typed:
class Greeter:
def hello(): # forgot self
return "hi"
def greet(name): # forgot self, has one real parameter
return "hi " + name
g = Greeter()
for call in ["g.hello()", "g.greet('Ann')"]:
try:
eval(call)
except TypeError as e:
print(f"{call:15} TypeError: {e}")
Output:
g.hello() TypeError: Greeter.hello() takes 0 positional arguments but 1 was given
g.greet('Ann') TypeError: Greeter.greet() takes 1 positional argument but 2 were given
"takes 1 positional argument but 2 were given" for a call with one argument almost always means the method has no self. Add self, or mark the method @staticmethod if it doesn't use the instance:
class Greeter:
def hello(self):
return "hi"
def greet(self, name):
return "hi " + name
@staticmethod
def shout(name): # no self needed: make it a staticmethod
return name.upper()
g = Greeter()
print(g.hello(), "|", g.greet("Ann"), "|", g.shout("ann"), "|", Greeter.shout("bob"))
Output:
hi | hi Ann | ANN | BOB
2. Plain functions: too many arguments, or a tuple that should be unpacked
def add(a, b):
return a + b
pair = (1, 2)
for call in ["add(pair)", "add(1, 2, 3)", "add(*pair)"]:
try:
print(f"{call:13}", eval(call))
except TypeError as e:
print(f"{call:13} TypeError: {e}")
Output:
add(pair) TypeError: add() missing 1 required positional argument: 'b'
add(1, 2, 3) TypeError: add() takes 2 positional arguments but 3 were given
add(*pair) 3
Passing a tuple as one argument gives the opposite error (missing 1 required positional argument). Unpack it with *.
3. threading / multiprocessing args=("abc") without a trailing comma
import threading
def work(n):
print("work got", n)
try:
threading.Thread(target=work, args=("abc")).run() # ("abc") is just a string
except TypeError as e:
print("TypeError:", e)
threading.Thread(target=work, args=("abc",)).run() # trailing comma makes a tuple
Output:
TypeError: work() takes 1 positional argument but 3 were given
work got abc
("abc") is just the string "abc", so each character becomes an argument: 3 were given. A one-element tuple needs a trailing comma: ("abc",). The same applies to multiprocessing.Process and Pool.apply_async.
4. Keyword-only parameters
def connect(host, *, timeout=5): # timeout is keyword-only
return f"{host} t={timeout}"
for call in ["connect('db', 10)", "connect('db', timeout=10)"]:
try:
print(f"{call:26}", eval(call))
except TypeError as e:
print(f"{call:26} TypeError: {e}")
print(sorted([3, 1, 2], key=None, reverse=True))
try:
sorted([3, 1, 2], None, True)
except TypeError as e:
print("sorted TypeError:", e)
Output:
connect('db', 10) TypeError: connect() takes 1 positional argument but 2 were given
connect('db', timeout=10) db t=10
[3, 2, 1]
sorted TypeError: sorted expected 1 argument, got 3
Parameters after * (and some built-ins) must be passed by name. Built-ins written in C word the error differently ("expected 1 argument, got 3").
5. A decorator's wrapper drops the arguments
def log(func):
def wrapper(): # wrapper drops the arguments
return func()
return wrapper
@log
def double(x):
return x * 2
try:
double(4)
except TypeError as e:
print("TypeError:", e)
import functools
def log(func):
@functools.wraps(func)
def wrapper(*args, **kwargs): # pass everything through
return func(*args, **kwargs)
return wrapper
@log
def double(x):
return x * 2
print(double(4))
Output:
TypeError: log.<locals>.wrapper() takes 0 positional arguments but 1 was given
8
The error names wrapper, not your function, which is the clue. Give the wrapper *args, **kwargs and forward them. For the related keyword error, see got multiple values for argument.
Frequently asked questions
Why does it say 2 were given when I passed one argument?
You called a method. Python passes the instance as the first argument, so the method needs self as its first parameter.
How do I fix takes 0 positional arguments but 1 was given?
Add self to the method definition (def hello(self):) or decorate it with @staticmethod.
Why does threading.Thread say 3 were given?
args=('abc') is a string, not a tuple, so each character becomes an argument. Use args=('abc',).
Written with AI assistance. Measured on 2026-10-22 on Debian with Python 3.13.5: methods without self, staticmethod, tuple unpacking, threading args without a trailing comma, keyword-only parameters and a decorator wrapper. Every block was run verbatim and its output pasted unedited. PlainHeaders is our extension; Python is free.