Содержание
  1. Что означает unexpected argument и почему Python его отвергает
  2. Дословный трейсбек: что печатает Python 3.14.3
  3. Подсказка Did you mean: с какой версии Python сам называет верное имя
  4. Причины возникновения unexpected argument: девять сценариев, три формы сообщения
  5. Имя функции в ошибке отличается от имени в вашем вызове
  6. Когда unexpected argument прилетает после обновления библиотеки
  7. Как исправить ошибку unexpected argument: пять починок, каждая прогнана
  8. Декоратор, который возвращает контроль имен при использовании **kwargs
  9. Схема разбора: от текста ошибки к починке за три шага
  10. Что стало с сообщением keyword can’t be an expression
  11. Чек-лист: как быстро закрыть unexpected argument
  12. Частые вопросы про unexpected argument
СправочникОбновлено · 09.2026

Что означает ошибка TypeError: function got an unexpected keyword argument в Python?

22 апреля 2024 · 16 минут чтения

TypeError: got an unexpected keyword argument означает ровно одно: имя, переданное при вызове, в сигнатуре функции отсутствует. Python сопоставляет ключевые аргументы с параметрами определения по имени и отвергает всё лишнее. Починка — один шаг из трёх: привести имя к сигнатуре, принять лишние ключи через **kwargs или отфильтровать словарь перед распаковкой. Начиная с Python 3.13 интерпретатор сам называет правильное имя в тексте ошибки.

  • Сообщение приходит на этапе вызова: тело функции не выполнялось ни разу.
  • Подсказка Did you mean 'name'? появляется, когда у параметра похожее имя.
  • Имя функции в тексте ошибки может отличаться от имени, которое вы написали в коде.
  • Тот же класс ошибки даёт распаковка **dict с лишним ключом и вызов после обновления библиотеки.
  • Параметры до / дают другое сообщение — got some positional-only arguments passed as keyword arguments.

Что означает unexpected argument и почему Python его отвергает

Два повода, с которых начинается разбор. Первый — неправильное имя ключевого аргумента: в вызове стоит nam, в определении функции name. Второй — использование ключевых аргументов без поддержки произвольных имён: вызов с лишним ключом у функции, где **kwargs не объявлен. Прогон из раздела «Причины возникновения unexpected argument» показывает ещё семь поводов, и механика у всех одна. Ключевой аргумент — это пара «имя=значение» в вызове. Интерпретатор берёт имя из вызова и ищет параметр с таким же именем в определении функции. Совпадения нет — вызов прерывается до входа в тело, и наружу выходит TypeError. Документация Python описывает этот класс исключений дословно так: «Raised when an operation or function is applied to an object of inappropriate type. The associated value is a string giving details about the type mismatch».

Отсюда первое практическое следствие: трейсбек указывает на строку вызова, а внутри функции ничего не исполнялось. Переменные, которые вы там ожидали увидеть отладчиком, ещё не созданы. Разбор всегда начинается с сигнатуры, и полезно помнить разницу между функциями и методами в Python: у метода первым параметром стоит self, и счёт «лишних» ключей у него сдвинут.

Второе следствие: сообщение говорит об именах. Значение аргумента интерпретатор на этом этапе даже не смотрит, тип проверять некому. Поэтому приводить строки к числам и менять порядок аргументов бесполезно — пока имя расходится с параметром, результат тот же.

Дословный трейсбек: что печатает Python 3.14.3

Ниже прогон на Windows-сборке CPython 3.14.3 (tags/v3.14.3:323c59a, Feb 3 2026, MSC v.1944 64 bit). Файл из пяти строк, вызов с опечаткой в имени параметра:

import sys
print(sys.version)

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

greet(nam="Alice")

Вывод интерпретатора целиком, без сокращений:

3.14.3 (tags/v3.14.3:323c59a, Feb  3 2026, 16:04:56) [MSC v.1944 64 bit (AMD64)]
Traceback (most recent call last):
  File "t1.py", line 7, in <module>
    greet(nam="Alice")
    ~~~~~^^^^^^^^^^^^^
TypeError: greet() got an unexpected keyword argument 'nam'. Did you mean 'name'?

Читать этот вывод стоит снизу вверх. Последняя строка называет функцию (greet), проблемное имя ('nam') и готовую замену ('name'). Строка с тильдами и «крышками» под кодом — точные координаты: тильды покрывают вызываемый объект, крышки — скобки с аргументами. Когда в одной строке два-три вложенных вызова, эта разметка показывает, какой именно из них упал.

Порядок вывода говорит о том же: строка с версией напечаталась, строка Hello — нет. Программа дошла до вызова и остановилась на нём.

Подсказка Did you mean: с какой версии Python сам называет верное имя

Строка Did you mean 'name'? в тексте ошибки — это готовый ответ, который остаётся подставить в вызов. Её добавили в CPython 3.13. Официальный разбор новшеств Python 3.13 формулирует это дословно: «The error message now tries to suggest the correct keyword argument when an incorrect keyword argument is passed to a function», и приводит пример со стандартным методом:

>>> "Better error messages".split(max_split=1)
Traceback (most recent call last):
  File "<python-input-0>", line 1, in <module>
    "Better error messages".split(max_split=1)
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
TypeError: split() got an unexpected keyword argument 'max_split'. Did you mean 'maxsplit'?

Практический вывод для диагностики: если вы видите unexpected argument без хвоста «Did you mean», возможны два случая. Первый — интерпретатор старше 3.13, и подсказку печатать просто нечем. Второй — версия свежая, а похожего имени в сигнатуре нет вовсе: параметр отсутствует целиком, переименование тут ни при чём. Различить их помогает одна команда в терминале: python -V.

Разница меняет план починки. На версиях до 3.13 сигнатуру приходится смотреть руками. На 3.13 и выше отсутствие подсказки само по себе информативно: гипотезу «опечатка» можно закрывать и переходить к причинам, по которым параметра нет вовсе — другая версия библиотеки, другой объект, другой класс.

Причины возникновения unexpected argument: девять сценариев, три формы сообщения

Чтобы понять, на что вообще похож этот TypeError, мы собрали скрипт из девяти сценариев и прогнали его одним запуском на Python 3.14.3. Прибор напечатал: сценариев 9, различных форм сообщения 3, подсказка «Did you mean» — в 3 случаях из 9.

Сценарий Дословный текст ошибки
Опечатка в имени параметра TypeError: greet() got an unexpected keyword argument 'nam'. Did you mean 'name'?
Имени нет в сигнатуре TypeError: calculate() got an unexpected keyword argument 'z'
Распаковка словаря **d TypeError: calculate() got an unexpected keyword argument 'z'
Параметры до / переданы по имени TypeError: posonly() got some positional-only arguments passed as keyword arguments: 'a, b'
Опечатка в keyword-only параметре после * TypeError: kwonly() got an unexpected keyword argument 'moode'. Did you mean 'mode'?
Встроенная функция sorted TypeError: sort() got an unexpected keyword argument 'keys'. Did you mean 'key'?
Наследование через super().__init__(**kw) TypeError: Base.__init__() got an unexpected keyword argument 'nmae'
functools.partial TypeError: calculate() got an unexpected keyword argument 'z'
Сгенерированный __init__ у dataclass TypeError: P.__init__() got an unexpected keyword argument 'z'

Из таблицы видно главное для диагностики: восемь сценариев из девяти дают одну и ту же формулировку про keyword argument, и различает их только имя функции слева. Девятый выпадает отдельным текстом про positional-only — это другая причина и другая починка.

Имя функции в ошибке отличается от имени в вашем вызове

Неочевидная ловушка этого TypeError: слева от «got an unexpected keyword argument» стоит имя того, кто реально принимал аргументы, и оно совпадает с написанным в коде далеко не всегда. Два случая из нашего прогона на Python 3.14.3.

Встроенная функция. Вызов sorted([3,1,2], keys=None) отвечает так:

TypeError: sort() got an unexpected keyword argument 'keys'. Did you mean 'key'?

В коде написано sorted, в ошибке — sort. Грепать проект по слову sort в такой ситуации бессмысленно. Верный шаг — спросить сигнатуру у самого интерпретатора: inspect.signature(sorted) печатает (iterable, /, *, key=None, reverse=False), и правильное имя key видно сразу.

Наследование. Класс-наследник принимает **kw и передаёт их дальше:

class Base:
    def __init__(self, name): ...

class Child(Base):
    def __init__(self, **kw):
        super().__init__(**kw)

Child(nmae="x")

Результат прогона:

TypeError: Base.__init__() got an unexpected keyword argument 'nmae'

Вызывали Child, а претензию предъявляет Base.__init__, потому что **kw у наследника принимает всё подряд и отдаёт проблему выше по цепочке. В трейсбеке при этом видно два кадра: строку с Child(nmae="x") и строку с super().__init__(**kw). Внутри класса такие вещи легче ловить, когда сигнатуры дандер-методов перед глазами — например, при реализации методов __add__() и __radd__() действует то же правило совпадения имён.

Правило для обоих случаев: имя из сообщения — это подсказка, где искать определение, а строка трейсбека выше показывает, где стоит вызов.

Когда unexpected argument прилетает после обновления библиотеки

Код не менялся, а вызов вдруг падает — типичный сюжет после pip install -U. Параметр, который библиотека принимала в прошлой версии, в новой убрали или переименовали. Мы воспроизвели это у себя: один и тот же вызывающий файл и две версии модуля mailer, отличающиеся одним параметром.

# v1/mailer.py
def send(to, text, use_context=True): ...

# v2/mailer.py
def send(to, text): ...

# caller.py
import mailer
print(mailer.send(to="a@b.ru", text="hi", use_context=True))

Прогон на Python 3.14.3 с первой версией в sys.path даёт v1 -> a@b.ru: hi (use_context=True). Тот же файл со второй версией:

Traceback (most recent call last):
  File "caller.py", line 4, in <module>
    print(mailer.send(to="a@b.ru", text="hi", use_context=True))
          ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: send() got an unexpected keyword argument 'use_context'

Подсказки «Did you mean» здесь нет, и это диагностический признак: похожего имени в новой сигнатуре не осталось, поэтому подставлять интерпретатору нечего. Порядок разбора такой: pip show имя_пакета покажет установленную версию, inspect.signature(mailer.send) — реальный набор параметров, changelog библиотеки — под каким именем параметр живёт теперь.

Риск выше там, где библиотека меняется быстро: обёртки вокруг API нейросетей, клиенты мессенджеров, SDK платёжных систем — у них сигнатуры переезжают между мажорными версиями. Если вы собираете Telegram-бота на Python и OpenAI, привычка сверять сигнатуру с установленной версией экономит вечер.

Как исправить ошибку unexpected argument: пять починок, каждая прогнана

Ниже рабочие варианты. Каждый мы запустили одним файлом и приводим фактический вывод интерпретатора, чтобы вариант можно было скопировать и проверить у себя.

import inspect, sys
print("Python", sys.version.split()[0])

# 1. Привести имя к сигнатуре
def greet(name): return f"Hello, {name}"
print("fix1:", greet(name="Alice"))

# 2. Принять лишние ключи через **kwargs
def calculate(x, y, **kwargs): return x + y, kwargs
print("fix2:", calculate(x=5, y=3, z=2))

# 3. Отфильтровать словарь по сигнатуре ДО распаковки
def calc2(x, y): return x + y
data = {"x": 5, "y": 3, "z": 2, "source": "crm"}
allowed = set(inspect.signature(calc2).parameters)
clean = {k: v for k, v in data.items() if k in allowed}
print("fix3: отброшено", sorted(set(data) - allowed), "->", calc2(**clean))

# 4. Позиционно-только параметры передать позиционно
def posonly(a, b, /): return a + b
print("fix4:", posonly(1, 2))

# 5. Сверить сигнатуру установленной версии
print("fix5:", inspect.signature(str.split))

Фактический вывод:

Python 3.14.3
fix1: Hello, Alice
fix2: (8, {'z': 2})
fix3: отброшено ['source', 'z'] -> 8
fix4: 3
fix5: (self, /, sep=None, maxsplit=-1)

Третий вариант лечит причину, когда аргументы приходят из внешних данных: JSON от API, строка базы, форма. Словарь фильтруется по реальным параметрам функции, лишние ключи отбрасываются осознанно, и распаковка **clean больше не может принести неожиданное имя. В нашем прогоне отброшены source и z, результат вызова — 8.

Второй вариант с **kwargs удобен, но у него есть цена: функция перестаёт сообщать об опечатках вовсе. Вызов calculate(x=5, y=3, zz=2) после такой правки пройдёт молча, и ошибка всплывёт дальше по коду в виде неверного результата. Документация Python описывает поведение **name так: «it receives a dictionary containing all keyword arguments except for those corresponding to a formal parameter».

Декоратор, который возвращает контроль имен при использовании **kwargs

У починки через **kwargs есть цена: функция проглатывает любые имена, включая неправильное, и unexpected argument больше не возникает даже там, где он был бы полезен. Декоратор снимает эту цену — он сверяет ключи вызова с сигнатурой и падает раньше, с внятным текстом. Ниже пример использования, прогнанный на Python 3.14.3.

import inspect, functools, sys
print("Python", sys.version.split()[0])

def strict_kwargs(func):
    params = inspect.signature(func).parameters
    named = {n for n, p in params.items()
             if p.kind in (p.POSITIONAL_OR_KEYWORD, p.KEYWORD_ONLY)}

    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        extra = sorted(set(kwargs) - named)
        if extra:
            raise TypeError(
                f"{func.__name__}(): unexpected keyword arguments {extra}; "
                f"expected {sorted(named)}")
        return func(*args, **kwargs)
    return wrapper

@strict_kwargs
def calculate(x, y, **kwargs):
    return x + y

print("ok:", calculate(x=5, y=3))
try:
    calculate(x=5, y=3, z=2)
except TypeError as e:
    print("TypeError:", e)

Фактический вывод прогона:

Python 3.14.3
ok: 8
TypeError: calculate(): unexpected keyword arguments ['z']; expected ['x', 'y']

Здесь есть тонкость, из-за которой наивная версия декоратора врёт. Проверка наличия ключей идёт по именованным параметрам: из signature().parameters берутся только виды POSITIONAL_OR_KEYWORD и KEYWORD_ONLY. Сам **kwargs тоже лежит в parameters под именем kwargs, и без фильтра по виду параметра он попадает в список ожидаемых имен — в первом прогоне мы получили именно такое сообщение, с посторонним 'kwargs' в перечне.

Тот же приём годится для логирования и для проверки типизации: обёртка видит и сигнатуру, и фактические аргументы вызова, поэтому управление ими целиком лежит в декораторе, а тело функции остаётся без изменения.

Схема разбора: от текста ошибки к починке за три шага

Разбор unexpected argument за три шага
Разбор unexpected argument за три шага

Алгоритм, которым мы разбирали девять сценариев прогона на Python 3.14.3, укладывается в три вопроса к самому тексту ошибки.

Шаг 1. Прочитать текст после двоеточия. Формулировка got some positional-only arguments passed as keyword arguments означает параметры до / и лечится передачей позиционно. Формулировка got an unexpected keyword argument ведёт к шагу 2.

Шаг 2. Посмотреть, есть ли хвост Did you mean. Есть — это опечатка, имя из подсказки подставляется в вызов, разбор закончен. Нет — на 3.13 и выше это значит, что похожего параметра в сигнатуре не нашлось, и разбор идёт на шаг 3.

Шаг 3. Спросить сигнатуру у интерпретатора. inspect.signature(объект) печатает реальный набор параметров той версии, которая установлена сейчас. Дальше решение: править имя в вызове, фильтровать входной словарь или обновлять код под новую сигнатуру библиотеки.

Три шага закрывают и случаи, где имя в ошибке не совпадает с именем вызова: сигнатуру спрашивают у объекта из кода, а интерпретатор сам показывает, что у него внутри.

Что стало с сообщением keyword can’t be an expression

Запрос «keyword can t be an expression» до сих пор живёт в подсказках поиска, хотя современный интерпретатор такого текста уже не печатает. Это соседняя ошибка: она возникает, когда слева от знака «равно» в вызове стоит выражение — атрибут, индекс, строковый литерал — вместо простого имени параметра. Мы прогнали обе типовые формы на Python 3.14.3.

def f(name=None): pass
obj = type("O", (), {})()
f(obj.name="x")
  File "t4.py", line 3
    f(obj.name="x")
      ^^^^^^^^^
SyntaxError: expression cannot contain assignment, perhaps you meant "=="?

То же самое со строковым литералом вместо имени параметра:

f("name"="x")
SyntaxError: expression cannot contain assignment, perhaps you meant "=="?

И третья родственная формулировка — повтор одного имени в вызове:

  File "t6.py", line 2
    f(a=1, a=2)
           ^^^
SyntaxError: keyword argument repeated: a

Ключевое отличие от unexpected argument — момент срабатывания. Все три сообщения выдаёт парсер до запуска программы, поэтому ни одна строка файла не выполнится, даже если ошибка стоит в самом конце. TypeError про unexpected argument, наоборот, возникает уже во время работы, и предыдущие строки к этому моменту отработали. Подробнее о том, как читать сообщения парсера, — в разборе ошибки SyntaxError: invalid syntax.

Имена ключевых аргументов подчиняются правилам идентификаторов: буквы, цифры и подчёркивание, без точек и кавычек. Передать значение по вычисляемому ключу можно только через словарь и распаковку: f(**{"name": "x"}).

Чек-лист: как быстро закрыть unexpected argument

Признак в сообщении Что это значит Починка
Есть хвост Did you mean 'X'? Опечатка в имени параметра Подставить имя из подсказки
Хвоста нет, Python 3.13 и выше Похожего параметра в сигнатуре нет Сверить inspect.signature и версию пакета
positional-only arguments passed as keyword Параметры стоят до / Передать позиционно, без имени
Имя функции в ошибке другое Аргументы принял вложенный вызов или родительский класс Искать определение по имени из ошибки
Ошибка появилась после обновления Сигнатура библиотеки изменилась pip show плюс changelog версии
Аргументы приходят из JSON или формы В словаре лишние ключи Фильтр словаря по signature().parameters
SyntaxError вместо TypeError Слева от «равно» стоит выражение Простое имя параметра или распаковка словаря

Две операции из таблицы стоит освоить первыми: проверка имен по сигнатуре и изменение определения функции под фактический вызов. Примеры обеих — в разделах «Как исправить ошибку unexpected argument» и «Декоратор, который возвращает контроль имен», с дословным выводом интерпретатора.

Первая проверка перед долгим разбором — python -V. Подсказка «Did you mean» для ключевых аргументов появилась в 3.13, поэтому её отсутствие на 3.12 и на 3.13 значит разные вещи, и одна эта строка задаёт всю дальнейшую ветку разбора.

Частые вопросы про unexpected argument

Что означает ошибка TypeError: got an unexpected keyword argument?

Что имя, переданное при вызове, отсутствует в сигнатуре функции. Python сопоставляет ключевые аргументы с параметрами определения по именам и прерывает вызов до входа в тело функции.

С какой версии Python сам подсказывает правильное имя аргумента?

С версии 3.13. Интерпретатор добавляет к сообщению хвост вида Did you mean ‘name’?, если в сигнатуре есть похожее имя. На 3.12 и ниже такого хвоста нет, и сигнатуру приходится смотреть руками.

Почему имя функции в тексте ошибки отличается от того, которое я вызывал?

Потому что имя в сообщении принадлежит тому объекту, который реально принимал аргументы. Вызов sorted отвечает от имени sort, а конструктор наследника с **kw передаёт проблему в Base.__init__ родительского класса.

Как передать словарь в функцию, чтобы лишние ключи не ломали вызов?

Отфильтровать словарь по сигнатуре перед распаковкой: allowed = set(inspect.signature(func).parameters), затем передать только пары, чьи ключи входят в allowed. Вариант с **kwargs тоже работает, но он прячет опечатки в именах.

Чем SyntaxError отличается от TypeError про unexpected argument?

Моментом срабатывания. Сообщения expression cannot contain assignment и keyword argument repeated выдаёт парсер до запуска программы, поэтому не выполнится ни одна строка файла. TypeError про unexpected argument возникает во время работы, когда предыдущие строки уже отработали.

Читайте также

3 материала