Fixing TypeError lambda() missing 1 required positional argument checked in Qt signals

Why connecting signals with lambda in PySide6 and PyQt6 can go wrong, and how to fix it
Heads up! You've already completed this tutorial.

I'm trying to pass extra data through a Qt signal using a lambda, for example when connecting triggered or clicked signals to actions created in a loop. But I get TypeError: <lambda>() missing 1 required positional argument: 'checked'. I've tried every combination I can think of and nothing works. How do I fix this?

This is one of the most common stumbling blocks when working with signals and slots in PySide6 and PyQt6. You're connecting a signal like clicked or triggered to a lambda, and you want to pass some extra data along — like a filename or a value from a loop. It looks like it should work, but instead you get a confusing TypeError.

Let's walk through why this happens, and then look at two clean ways to solve it.

The Problem

Suppose you're building a list of buttons in a loop, and you want each button click to call a method with a different value:

python
for value in ["A", "B", "C"]:
    button = QPushButton(value)
    button.clicked.connect(lambda val=value: self.handle_click(val))

Or maybe you're building a "Recent Files" menu:

python
for file in recent_files:
    action = QAction(file, self)
    menu.addAction(action)
    action.triggered.connect(lambda filename=file: self.open_file(filename))

In both cases, you might see:

python
TypeError: <lambda>() missing 1 required positional argument: 'checked'

Or, perhaps even more confusingly, your method receives False instead of the filename or value you expected.

Why This Happens

Both the clicked and triggered signals can send a checked boolean parameter. Whether they actually send it (and whether your slot must accept it) depends on which version and binding of Qt you're using. The behavior has varied between PyQt5, PyQt6, PySide2, and PySide6.

When the signal does send the checked value, it gets passed as the first positional argument to your lambda. If your lambda isn't expecting it, you get the TypeError. If your lambda is using a keyword argument like filename=file, the checked boolean overwrites it — which is why you might see your app trying to open a file called False.

Here's what's happening step by step:

  1. The signal triggered(checked) emits with one argument: False (or True for checkable actions).
  2. Your lambda lambda filename=file: ... has one keyword parameter.
  3. Python assigns the signal's positional argument (False) to filename, overwriting the default you set.

Accept checked in Your Lambda

The most straightforward fix is to explicitly accept the checked argument in your lambda, and use a separate keyword argument for your extra data:

python
for file in recent_files:
    action = QAction(file, self)
    menu.addAction(action)
    action.triggered.connect(lambda checked, filename=file: self.open_file(filename))

Here, checked catches the boolean that the signal sends, and filename keeps the value you assigned from the loop. The checked value is simply ignored inside the lambda body.

The same pattern works for clicked:

python
for value in ["A", "B", "C"]:
    button = QPushButton(value)
    button.clicked.connect(lambda checked, val=value: self.handle_click(val))

If you want to handle both cases where the signal may or may not send the checked parameter, you can use *args:

python
button.clicked.connect(lambda *args, val=value: self.handle_click(val))

The *args absorbs any positional arguments the signal sends (zero or one), and val stays safely as a keyword argument.

Use functools.partial Instead

An alternative that avoids lambda altogether is functools.partial. This creates a new callable with some arguments pre-filled:

python
from functools import partial

for file in recent_files:
    action = QAction(file, self)
    menu.addAction(action)
    action.triggered.connect(partial(self.open_file, file))

With partial, Qt's signal system recognizes that self.open_file accepts one argument and that it's already been provided. The extra checked argument from the signal is handled gracefully — Qt will pass it as an additional argument, and since open_file only accepts one (beyond self), it's simply discarded.

This approach tends to be cleaner when you're working in loops, because you don't need to worry about variable scoping or the checked parameter at all.

The Loop Variable Trap

While we're here, it's worth mentioning a related issue that often appears alongside this one. If you write a lambda in a loop without capturing the loop variable as a default argument, every lambda ends up using the last value of the variable:

python
# ❌ Bug: all lambdas will use the last value of `file`
for file in recent_files:
    action = QAction(file, self)
    action.triggered.connect(lambda checked: self.open_file(file))

This happens because the lambda captures the variable file, not its value at the time the lambda was created. By the time any action is triggered, the loop has finished and file holds its final value.

The fix is to capture the current value using a default keyword argument:

python
# ✅ Correct: each lambda captures its own copy of `file`
for file in recent_files:
    action = QAction(file, self)
    action.triggered.connect(lambda checked, filename=file: self.open_file(filename))

Or, use functools.partial, which naturally captures the value at the time it's called:

python
# ✅ Also correct
action.triggered.connect(partial(self.open_file, file))

Complete Working Example

Here's a full example that demonstrates both approaches — lambda and functools.partial — in a working application with a "Recent Files" menu:

python
import sys
from functools import partial

from PyQt6.QtGui import QAction
from PyQt6.QtWidgets import (
    QApplication,
    QMainWindow,
    QMessageBox,
)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Recent Files Example")

        # Simulated list of recent files.
        recent_files = [
            "report_2024.pdf",
            "notes.txt",
            "photo.png",
        ]

        menubar = self.menuBar()
        file_menu = menubar.addMenu("&File")

        # --- Approach 1: Using lambda ---
        lambda_menu = file_menu.addMenu("Open Recent (lambda)")
        for file in recent_files:
            action = QAction(file, self)
            lambda_menu.addAction(action)
            action.triggered.connect(
                lambda checked, filename=file: self.open_file(filename)
            )

        # --- Approach 2: Using functools.partial ---
        partial_menu = file_menu.addMenu("Open Recent (partial)")
        for file in recent_files:
            action = QAction(file, self)
            partial_menu.addAction(action)
            action.triggered.connect(partial(self.open_file, file))

    def open_file(self, filename):
        QMessageBox.information(
            self,
            "Opening File",
            f"You selected: {filename}",
        )


app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec()

Run this and try clicking the different menu items. Both submenus work correctly — each action opens a message box showing the correct filename.

Which Approach Should You Use?

Both work well. The lambda approach gives you more flexibility if you need to do something more complex inside the slot connection. The functools.partial approach is more concise and sidesteps the checked issue entirely, making it a good default choice when you're simply forwarding a value to a method.

Whichever you choose, the pattern is the same: make sure your callable accounts for the checked argument that Qt's signals may send, and capture loop variables by value rather than by reference.

Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak

Create GUI Applications with Python & Qt6 by Martin Fitzpatrick

(PySide6 Edition) The hands-on guide to making apps with Python — Over 15,000 copies sold!

More info Get the book

Martin Fitzpatrick

Fixing TypeError lambda() missing 1 required positional argument checked in Qt signals was written by Martin Fitzpatrick.

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt. Martin founded PythonGUIs to provide easy to follow GUI programming tutorials to the Python community. He has written a number of popular Python books on the subject.