Skip to content

Worker fails to start when kwargs is not provided to PsycopgConnector #1483

@fnxL

Description

@fnxL

Worker fails to start if I do not provide a kwargs argument when initializing the PsycopgConnector in the App.
If I do provide a kwargs object, everything works fine.

This leads to the following runtime error:
TypeError: AsyncConnection.connect() argument after ** must be a mapping, not NoneType

It appears that kwargs ends up as None, which later gets expanded using **kwargs inside psycopg_connector.py, causing the crash.
I am not sure whether this is due to a breaking change in psycopg or in procrastinate but I thought it should be reported.

Proposed fix:

A simple fix in the PsycopgConnector constructor prevents the error:

File: psycopg_connector.py
Line: ~95
self._pool_args = kwargs if kwargs else {}

This ensures kwargs is always a mapping, avoiding the TypeError.

Version:

Python 3.13.5

"procrastinate>=3.6.0"
"psycopg[binary,pool]>=3.3.2"

Platform: Windows

Steps to reproduce:

import asyncio
import logging
import sys
from procrastinate import App, PsycopgConnector

logging.basicConfig(level=logging.DEBUG)

if sys.platform == "win32":
    asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

app = App(
    connector=PsycopgConnector(
        conninfo="postgresql://postgres:secret@127.0.0.1:5432/postgres",
    ),
)

app.run_worker()

uv run run.py

Traceback:

❯ uv run ./run.py 
WARNING:procrastinate.blueprints:App is instantiated in the main Python module (./run.py). See https://procrastinate.readthedocs.io/en/stable/discussions.html#top-level-app
INFO:procrastinate.blueprints:Adding tasks from blueprint
DEBUG:asyncio:Using selector: SelectSelector
DEBUG:procrastinate.app:All tasks imported
DEBUG:procrastinate.worker:Pruning stalled workers with old heartbeats
DEBUG:procrastinate.worker:Registered worker 21 in the database
INFO:procrastinate.worker.worker:Starting worker on all queues
WARNING:procrastinate.signals:Skipping signal handling, does not work on Windows
DEBUG:procrastinate.worker:Waiting for 10.0s before updating worker heartbeat
INFO:procrastinate.periodic:No periodic task found, periodic deferrer will not run.
DEBUG:procrastinate.worker:waiting for 5.0s before querying jobs to abort
ERROR:procrastinate.worker.worker:Side task listener failed with exception: psycopg.connection_async.AsyncConnection.connect() argument after ** must be a mapping, not NoneType, stopping worker
Traceback (most recent call last):
  File "...\.venv\Lib\site-packages\procrastinate\manager.py", line 566, in listen_for_jobs
    await self.connector.listen_notify(
    ...<2 lines>...
    )
  File "...\AppData\Roaming\uv\python\cpython-3.13.5-windows-x86_64-none\Lib\contextlib.py", line 101, in inner        
    return await func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\.venv\Lib\site-packages\procrastinate\psycopg_connector.py", line 258, in listen_notify
    async with self._get_standalone_connection() as connection:
               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "...\AppData\Roaming\uv\python\cpython-3.13.5-windows-x86_64-none\Lib\contextlib.py", line 214, in __aenter__   
    return await anext(self.gen)
           ^^^^^^^^^^^^^^^^^^^^^
  File "...\.venv\Lib\site-packages\procrastinate\psycopg_connector.py", line 245, in _get_standalone_connection
    async with await self.pool.connection_class.connect(
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        self.pool.conninfo, **self.pool.kwargs, autocommit=True
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ) as connection:
    ^
TypeError: psycopg.connection_async.AsyncConnection.connect() argument after ** must be a mapping, not NoneType
INFO:procrastinate.worker.worker:Stop requested
DEBUG:procrastinate.utils:Cancelled task deferrer
ERROR:procrastinate.utils:listener error: TypeError('psycopg.connection_async.AsyncConnection.connect() argument after ** must be a mapping, not NoneType')
Traceback (most recent call last):
  File "...\.venv\Lib\site-packages\procrastinate\manager.py", line 566, in listen_for_jobs
    await self.connector.listen_notify(
    ...<2 lines>...
    )
  File "...\AppData\Roaming\uv\python\cpython-3.13.5-windows-x86_64-none\Lib\contextlib.py", line 101, in inner        
    return await func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "...\.venv\Lib\site-packages\procrastinate\psycopg_connector.py", line 258, in listen_notify
    async with self._get_standalone_connection() as connection:
               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
  File "...\AppData\Roaming\uv\python\cpython-3.13.5-windows-x86_64-none\Lib\contextlib.py", line 214, in __aenter__   
    return await anext(self.gen)
           ^^^^^^^^^^^^^^^^^^^^^
  File "...\.venv\Lib\site-packages\procrastinate\psycopg_connector.py", line 245, in _get_standalone_connection
    async with await self.pool.connection_class.connect(
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
        self.pool.conninfo, **self.pool.kwargs, autocommit=True
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    ) as connection:
    ^
TypeError: psycopg.connection_async.AsyncConnection.connect() argument after ** must be a mapping, not NoneType
DEBUG:procrastinate.worker:Unregistered finished worker 21 from the database
INFO:procrastinate.worker.worker:Stopped worker on all queues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions