AttributeError: ‘PySide6 QtCore Signal’ Object Has No Attribute ‘Connect’ | Use .connect(), Not .Connect

The error AttributeError: ‘PySide6 QtCore Signal’ object has no attribute ‘Connect’ means your signal is being used with the wrong API casing or on the wrong object.

Why AttributeError: ‘PySide6 QtCore Signal’ Object Has No Attribute ‘Connect’ Appears

Qt for Python exposes signals as Python objects that follow PEP-8 style methods. The correct method is connect in lowercase. When code calls .Connect, Python looks for a member with that exact name on the Signal object and fails. The same crash can happen if you call connect on a class attribute instead of an instance, or if your class does not inherit from QObject properly. The runtime is simply telling you that it cannot find the member that you asked for.

Quick check: scan for any .Connect and switch to .connect. Then confirm the signal is accessed through an object instance, not the class itself.

Fix ‘Signal’ Object Has No Attribute ‘connect’ In PySide6 — Causes And Fixes

There are a handful of repeat offenders behind this crash. Use this table to match the symptom to a precise fix without guesswork.

Cause What You See Fix
Using .Connect instead of .connect AttributeError on Connect Call signal.connect(slot) with lowercase method
Calling connect on the class, not an instance AttributeError on connect or nothing happens Instantiate the class and use instance.signal.connect
Signal declared on a class that does not subclass QObject AttributeError on emit or connect Subclass QObject and call super().__init__() in __init__
Signal defined as an instance attribute Signal object not bound correctly Declare signals as class attributes on the QObject subclass
Mismatched signal signature and slot parameters Type errors when the signal fires Match the types and count of arguments or use a lambda to adapt
Cross-thread signal to a non-Qt object Slot never runs or crashes under load Connect to a QObject receiver or post to the main thread

Correct Signal And Slot Setup In PySide6

The reliable pattern is simple: declare the signal as a class attribute on a class that inherits QObject, create an instance, connect with lowercase connect, then emit with emit.

from PySide6.QtCore import QObject, Signal, Slot

class Worker(QObject):
    # class-level declaration
    finished = Signal(str)

    def __init__(self):
        super().__init__()

    def run(self):
        # do work, then report
        self.finished.emit("done")

class View(QObject):
    @Slot(str)
    def show_status(self, text):
        print("status:", text)

worker = Worker()
view = View()
# connect on the INSTANCE, using lowercase connect
worker.finished.connect(view.show_status)
worker.run()

This pattern avoids the crash because the signal lives on a real object, the casing is right, and the class is wired into Qt’s meta-object system via QObject and super().__init__().

Common Mistakes That Trigger The Error

  • Using C++ Casing — Writing .Connect or .Emit mirrors C++ habits. In Python, both are lowercase: .connect, .emit.
  • Connecting On The Class — Calling MyEmitter.my_signal.connect(...) reaches a descriptor, not a bound signal. Use an instance: my_emitter.my_signal.connect(...).
  • Skipping QObject Setup — If your emitter does not inherit QObject, or its constructor does not call super().__init__(), the signal will not function.
  • Defining Signals In __init__ — Signals must be class attributes. If you assign self.my_signal = Signal() inside __init__, Qt cannot register it.
  • Wrong Signature — Declaring Signal(int) but connecting to @Slot(str) causes runtime noise. Keep argument count and types aligned.
  • Lambda With Missing Args — If the signal emits data but the lambda ignores it incorrectly, you can lose values or break the call. Include placeholders like lambda value: handler(value).
  • Thread Jump Without A QObject Target — Emitting from a worker thread into a plain Python function can miss the GUI thread. Point the connection at a QObject that lives in the main thread.

Working Examples You Can Drop In

Lowercase connect And emit

from PySide6.QtCore import QObject, Signal

class Ping(QObject):
    pinged = Signal()

    def __init__(self):
        super().__init__()

def on_ping():
    print("ping")

p = Ping()
p.pinged.connect(on_ping)
p.pinged.emit()

Signal With Data And A Typed Slot

from PySide6.QtCore import QObject, Signal, Slot

class Meter(QObject):
    reading = Signal(float)

    def __init__(self):
        super().__init__()

class Display(QObject):
    @Slot(float)
    def update(self, value: float):
        print("reading:", value)

m = Meter()
d = Display()
m.reading.connect(d.update)
m.reading.emit(3.14)

Adapting Arguments With A Lambda

from PySide6.QtCore import QObject, Signal

class Meter(QObject):
    reading = Signal(float)
    def __init__(self):
        super().__init__()

def log(prefix: str, text: str):
    print(prefix, text)

meter = Meter()
meter.reading.connect(lambda v: log("value", str(v)))
meter.reading.emit(2.5)

Using Signals Across Threads Safely

Signals are a safe way to move work results from a background thread to the GUI thread. The connection between a worker and a receiver will default to an auto connection. When the objects live on different threads, that behaves as a queued connection, which keeps the GUI responsive.

from PySide6.QtCore import QObject, QThread, Signal, Slot

class Worker(QObject):
    done = Signal(str)
    def __init__(self):
        super().__init__()
    def run(self):
        # heavy work here
        self.done.emit("ok")

class Controller(QObject):
    @Slot(str)
    def show(self, text):
        print("done:", text)

thread = QThread()
worker = Worker()
worker.moveToThread(thread)
ctrl = Controller()

thread.started.connect(worker.run)
worker.done.connect(ctrl.show)
thread.start()
# later, quit cleanly
thread.quit(); thread.wait()

Quick check: keep the worker as a QObject, move it to the thread, connect before starting, and emit results rather than touching widgets from the worker.

Troubleshooting Checklist

  • Search And Replace — Replace every .Connect with .connect and every .Emit with .emit.
  • Verify QObject Lineage — Confirm each emitter inherits QObject and calls super().__init__().
  • Inspect Binding — Ensure you call instance.signal.connect, not Class.signal.connect.
  • Match Signatures — Align Signal(...) types with slot parameters or decorate slots with @Slot(...).
  • Audit Thread Use — For worker threads, emit to a receiver that lives on the main thread.
  • Log Connections — Print the receiver function and confirm the slot runs by logging inside it.

Practical Patterns You Can Reuse

These patterns keep code clean and prevent the crash from returning later.

  • Emitter Class Per Feature — Group related signals on a small QObject class. Keep names action-based such as data_ready and error.
  • Typed Slots For Clarity — Decorate slots with @Slot(type) so readers see expectations. It also guards against wrong connections.
  • Instance-Only Access — Never call MyClass.signal.connect on the class. Always connect on the object you created.
  • One Responsibility — Let workers emit plain data and keep UI work inside a receiver that owns widgets on the main thread.
  • Tear-Down Paths — When windows close, call disconnect or drop references so queued calls do not land on deleted objects.

Where This Differs From PyQt And C++

PySide6 mirrors Qt but sticks to Python naming. In C++ you call free functions like QObject::connect and emit signals using the language keyword. In PySide6, you call lowercase methods on Python objects: signal.connect and signal.emit. That change in surface area is the reason the uppercase .Connect slips in during porting or while reading C++ posts. Treat the Python API as the source of truth and the error disappears.

Recap: Fixing The Exact Error Fast

To resolve AttributeError: ‘PySide6 QtCore Signal’ object has no attribute ‘Connect’ in a minute, apply this sequence:

  1. Lowercase The Call — Change .Connect to .connect.
  2. Use An Instance — Connect on object.signal, not on the class name.
  3. Subclass QObject — Ensure the emitter inherits QObject and calls super().__init__().
  4. Keep Signals On The Class — Declare Signal(...) as a class attribute.
  5. Align Signatures — Match signal arguments with the slot or adapt with a lambda.

Follow that path and the crash vanishes, your connections stay readable, and your slots fire exactly when they should.