pytest-dev/pytest · error · TypeError

Error evaluating {scope_callable} while defining fixture '{f

Error message

Error evaluating {scope_callable} while defining fixture '{fixture_name}'.
Expected a function with the signature (*, fixture_name, config)

What it means

Raised by `_eval_scope_callable` when the dynamic scope callable passed to `@pytest.fixture(scope=callable)` either raises or does not accept the required keyword-only signature `(*, fixture_name, config)`. pytest calls the callable at collection time to compute the scope string; any exception is wrapped in this TypeError pointing at the offending callable.

Source

Thrown at src/_pytest/fixtures.py:1098

        fail(
            f"fixture function has more than one 'yield':\n\n"
            f"{Source(fixturefunc).indent()}\n"
            f"{fs}:{lineno + 1}",
            pytrace=False,
        )


def _eval_scope_callable(
    scope_callable: Callable[[str, Config], ScopeName],
    fixture_name: str,
    config: Config,
) -> ScopeName:
    try:
        # Type ignored because there is no typing mechanism to specify
        # keyword arguments, currently.
        result = scope_callable(fixture_name=fixture_name, config=config)  # type: ignore[call-arg]
    except Exception as e:
        raise TypeError(
            f"Error evaluating {scope_callable} while defining fixture '{fixture_name}'.\n"
            "Expected a function with the signature (*, fixture_name, config)"
        ) from e
    if not isinstance(result, str):
        fail(
            f"Expected {scope_callable} to return a 'str' while defining fixture '{fixture_name}', but it returned:\n"
            f"{result!r}",
            pytrace=False,
        )
    return result


class FixtureDef(Generic[FixtureValue]):
    """A container for a fixture definition.

    Note: At this time, only explicitly documented fields and methods are
    considered public stable API.
    """

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Define the callable as `def my_scope(*, fixture_name, config): ...` and return one of "function","class","module","package","session".
  2. Make sure any config option you read inside the callable is registered via `pytest_addoption`/`addini`.
  3. Catch/avoid exceptions inside the callable; return a safe default scope on edge cases.

Example fix

// before
def scope(fixture_name):          # wrong signature
    return "session"
@pytest.fixture(scope=scope)
def x(): yield
// after
def scope(*, fixture_name, config):
    return "session" if config.getoption("--ci") else "function"
@pytest.fixture(scope=scope)
def x(): yield
Defensive patterns

Strategy: validation

Validate before calling

import inspect

def check_scope_callable(fn):
    sig = inspect.signature(fn)
    params = [p for p in sig.parameters.values()]
    has_var_kw = any(p.kind == inspect.Parameter.VAR_KEYWORD for p in params)
    names = {p.name for p in params}
    if not ("fixture_name" in names and "config" in names) and not has_var_kw:
        raise TypeError("scope callable must accept (*, fixture_name, config)")

Type guard

def is_valid_scope_callable(fn) -> bool:
    import inspect
    try:
        sig = inspect.signature(fn)
    except (TypeError, ValueError):
        return False
    names = set(sig.parameters)
    return {"fixture_name", "config"}.issubset(names) or any(
        p.kind == inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values()
    )

Prevention

When it happens

Trigger: Passing a scope function with the wrong signature, e.g. `def scope(fixture_name)` (missing `config`), or a function that raises (returns based on a missing config option). pytest invokes `scope(fixture_name=..., config=...)` with keyword args.

Common situations: Writing a dynamic-scope fixture that reads `config.getini("...")` for an option that is not registered, or copying a signature from outdated docs. Using positional-only params.

Related errors


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/43eeafbc3e46c3fe.json. Report an issue: GitHub.