pytest-dev/pytest · error · ValueError

Specifying plugins as objects is not supported in pytester…

Error message

Specifying plugins as objects is not supported in pytester subprocess mode; specify by name instead: {plugin}

What it means

Thrown by Pytester.runpytest_subprocess() when any entry in pytester.plugins is not a string. Subprocess mode can only forward plugin names via `-p <name>`; it cannot pickle/ship plugin object instances across process boundaries.

Solutions

  1. Pass plugin names (strings) instead of objects: use 'myplugin' or 'mymod.plugin'.
  2. Use runpytest_inprocess() if you must register plugin objects.
  3. Ensure the plugin is importable in the subprocess (installed or on PYTHONPATH).

Example fix

// before
pytester.plugins = [MyPlugin()]
pytester.runpytest_subprocess()
// after
pytester.plugins = ["myplugin"]  # ensure it's pip-installed or on PYTHONPATH
pytester.runpytest_subprocess()
Defensive patterns

Strategy: type-guard

Validate before calling

for i, p in enumerate(pytester.plugins):
    if not isinstance(p, str):
        pytest.fail(f'plugin {i} is an object, not a name: {p!r}')
pytester.runpytest_subprocess()

Type guard

def all_plugins_named(plugins: list) -> bool:
    return all(isinstance(p, str) for p in plugins)

Prevention

When it happens

Trigger: Setting pytester.plugins = [MyPlugin()] (an object) then calling runpytest_subprocess(); writing a test that worked under runpytest_inprocess (which accepts objects) and switching to subprocess mode; appending a plugin module object instead of its dotted name.

Common situations: Migrating from inprocess to subprocess for isolation; plugin tests that register a plugin instance by object; helper fixtures that populate plugins list with instances.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/e6162192eb1b3b71. Report an issue: GitHub.

Appendix: source

Thrown at src/_pytest/pytester.py:1515

        ``-p`` command line option.  Additionally ``--basetemp`` is used to put
        any temporary files and directories in a numbered directory prefixed
        with "runpytest-" to not conflict with the normal numbered pytest
        location for temporary files and directories.

        :param args:
            The sequence of arguments to pass to the pytest subprocess.
        :param timeout:
            The period in seconds after which to timeout and raise
            :py:class:`Pytester.TimeoutExpired`.
        :returns:
            The result.
        """
        __tracebackhide__ = True
        p = make_numbered_dir(root=self.path, prefix="runpytest-", mode=0o700)
        args = (f"--basetemp={p}", *args)
        for plugin in self.plugins:
            if not isinstance(plugin, str):
                raise ValueError(
                    f"Specifying plugins as objects is not supported in pytester subprocess mode; "
                    f"specify by name instead: {plugin}"
                )
            args = ("-p", plugin, *args)
        args = self._getpytestargs() + args
        return self.run(*args, timeout=timeout)

    def spawn_pytest(self, string: str, expect_timeout: float = 10.0) -> pexpect.spawn:
        """Run pytest using pexpect.

        This makes sure to use the right pytest and sets up the temporary
        directory locations.

        The pexpect child is returned.
        """
        basetemp = self.path / "temp-pexpect"
        basetemp.mkdir(mode=0o700)
        invoke = " ".join(map(str, self._getpytestargs()))

View on GitHub (pinned to 0d6fbdeffa)