pytest 9.2: xdist_group tests run on different workers (--dist loadgroup)

pytest -n 4 --dist loadgroup -v
[gw1] PASSED tests/test_db.py::test_insert[0]
[gw3] PASSED tests/test_db.py::test_insert[1]
# expected on one worker, with the group in the ID: tests/test_db.py::test_insert[0]@db

Short answer: pytest 9.2.0 (27 October 2026) changed where a test's ID is stored, and pytest-xdist 3.8.0 still writes the loadgroup suffix to the old place. The @<group> suffix is lost, so tests marked xdist_group are spread over all workers, silently: everything still passes until tests that share a database, file or port collide. Pin pytest below 9.2, or keep 9.2 and add the small conftest.py shim below, until pytest-xdist releases its fix.

Why it happens

With --dist loadgroup, pytest-xdist marks grouped tests by appending @<group> to each test's node ID (item._nodeid = f"{item.nodeid}@{group}" in xdist/remote.py), and its scheduler sends every ID with the same suffix to one worker. pytest 9.2.0 moved node IDs to a structured NodeId stored in item._id, and the nodeid property now reads only that. Writing item._nodeid no longer changes the ID, so no test carries a group and the scheduler treats them like --dist load. pytest-xdist has merged a fix (PR #1388) but its latest release on PyPI is still 3.8.0. We reproduced it on 28 October 2026: on pytest 9.1.1 all six tests of one group ran on one worker in three runs out of three; on 9.2.0 they ran on three workers in every run.

Fix

  1. Check: run pytest -n 2 --dist loadgroup -v. If tests marked @pytest.mark.xdist_group do not show @<group> at the end of their ID, you are affected (pytest 9.2.0 with pytest-xdist 3.8.0).
  2. Quickest fix: pin pytest below 9.2 in your requirements, lock file or constraints, for example pytest>=9.1,<9.2, and reinstall.
  3. To stay on pytest 9.2, add this to the conftest.py at the root of your tests. It copies the suffixed ID pytest-xdist wrote into the field pytest 9.2 reads, and does nothing on older pytest or without xdist:
    # conftest.py: pytest 9.2 + pytest-xdist 3.8.0 --dist loadgroup workaround (remove after the next xdist release)
    import pytest
    
    
    @pytest.hookimpl(trylast=True)
    def pytest_collection_modifyitems(config, items):
        try:
            from _pytest.nodeid import coerce_node_id  # pytest >= 9.2 only
        except ImportError:
            return
        for item in items:
            wanted = item.__dict__.get("_nodeid")
            if isinstance(wanted, str) and wanted != item.nodeid:
                item._id = coerce_node_id(wanted)
    
  4. Run the check again: the grouped tests show @<group> and run on one worker.
  5. When a pytest-xdist release after 3.8.0 includes PR #1388, upgrade it and remove the pin or the shim.

Watch out

Sources

Did this fix it?

What's still not working?

Describe what happens and paste any error message. We read every report and fix the page.

Other errors breaking soon

All "breaking soon" fixes