Python: fix TypeError: NamedTuple() got an unexpected keyword argument

Hissss hiss hissss hissssss hiss hiss!

Take this code, defining a small NamedTuple with a keyword argument per field:

from typing import NamedTuple

Point = NamedTuple("Point", x=int, y=int)

Run it on Python 3.13 or 3.14, and you’ll see:

$ python3.14 example.py
/.../example.py:3: DeprecationWarning: Creating NamedTuple classes using keyword arguments is deprecated and will be disallowed in Python 3.15. Use the class-based or functional syntax instead.
  Point = NamedTuple("Point", x=int, y=int)

And on Python 3.15+, it’s broken:

$ python3.15 example.py
Traceback (most recent call last):
  ...
TypeError: NamedTuple() got an unexpected keyword argument 'x'

What’s up with that?

NamedTuple has always had two documented ways to define fields: the class-based syntax, and a functional syntax taking a list of (name, type) pairs. The keyword-argument style above was never one of them, it worked only as a side effect of the old implementation happening to accept **kwargs. This form was therefore deprecated and removed in Python 3.15, with NamedTuple’s signature now locked to positional-only.

From the release notes:

The undocumented keyword argument syntax for creating NamedTuple classes (for example, Point = NamedTuple("Point", x=int, y=int)) is no longer supported. Use the class-based syntax or the functional syntax instead. (Contributed by Bénédikt Tran in gh-133817.)

The fix

Switch to the class-based syntax, which is the more readable option, and gives you a normal class body to add methods or docstrings to later:

from typing import NamedTuple


class Point(NamedTuple):
    x: int
    y: int

Or, if you’d rather keep a one-liner, use the documented functional syntax, a list of (name, type) pairs, instead of keyword arguments:

from typing import NamedTuple

Point = NamedTuple("Point", [("x", int), ("y", int)])

Auto-fix this problem with Ruff

Ruff’s pyupgrade-derived rule convert-named-tuple-functional-to-class (UP014) rewrites both functional forms, the list-of-tuples version and this keyword-argument version, to class syntax automatically. As of Ruff 0.16, released July 2026, UP014 is one of the hundreds of rules Ruff now enables by default, so there’s nothing to switch on, just run:

$ ruff check --fix example.py
Found 2 errors (2 fixed, 0 remaining).

(If you’re on an older Ruff, add --select UP014, or the broader --select UP, to opt in explicitly.)

…turning our original example straight into:

from typing import NamedTuple


class Point(NamedTuple):
    x: int
    y: int

Fin

May you name your tuples well,

—Adam


Read my book Boost Your Git DX to Git better.


Subscribe via RSS, Twitter, Mastodon, or email:

One summary email a week, no spam, I pinky promise.

Related posts:

Tags: