{"record":{"id":"43eeafbc3e46c3fe","repo":"pytest-dev/pytest","slug":"error-evaluating-scope-callable-while-defining-f","errorCode":null,"errorMessage":"Error evaluating {scope_callable} while defining fixture '{fixture_name}'.\nExpected a function with the signature (*, fixture_name, config)","messagePattern":"Error evaluating (.+?) while defining fixture '(.+?)'\\.\nExpected a function with the signature \\(\\*, fixture_name, config\\)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/fixtures.py","lineNumber":1098,"sourceCode":"        fail(\n            f\"fixture function has more than one 'yield':\\n\\n\"\n            f\"{Source(fixturefunc).indent()}\\n\"\n            f\"{fs}:{lineno + 1}\",\n            pytrace=False,\n        )\n\n\ndef _eval_scope_callable(\n    scope_callable: Callable[[str, Config], ScopeName],\n    fixture_name: str,\n    config: Config,\n) -> ScopeName:\n    try:\n        # Type ignored because there is no typing mechanism to specify\n        # keyword arguments, currently.\n        result = scope_callable(fixture_name=fixture_name, config=config)  # type: ignore[call-arg]\n    except Exception as e:\n        raise TypeError(\n            f\"Error evaluating {scope_callable} while defining fixture '{fixture_name}'.\\n\"\n            \"Expected a function with the signature (*, fixture_name, config)\"\n        ) from e\n    if not isinstance(result, str):\n        fail(\n            f\"Expected {scope_callable} to return a 'str' while defining fixture '{fixture_name}', but it returned:\\n\"\n            f\"{result!r}\",\n            pytrace=False,\n        )\n    return result\n\n\nclass FixtureDef(Generic[FixtureValue]):\n    \"\"\"A container for a fixture definition.\n\n    Note: At this time, only explicitly documented fields and methods are\n    considered public stable API.\n    \"\"\"","sourceCodeStart":1080,"sourceCodeEnd":1116,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/fixtures.py#L1080-L1116","documentation":"_eval_scope_callable (fixtures.py:1098) invokes a dynamic scope function passed via @pytest.fixture(scope=callable). If calling it raises ANY Exception, pytest wraps that as TypeError with guidance that the callable must accept keyword-only 'fixture_name' and 'config'. This is strictly a signature/implementation problem in the user-supplied scope function.","triggerScenarios":"Passing scope=<function> whose signature is not (*, fixture_name, config), e.g. def scope(name): ...; the callable raising internally (e.g. config.getoption on a missing option); a lambda that ignores required kwargs.","commonSituations":"Trying to make scope depend on configuration but writing the wrong parameter names; using positional params instead of keyword-only; raising inside the scope function due to a typo or missing config option; copying a scope callable from an older pytest version with a different signature contract.","solutions":["Define the scope callable exactly as def my_scope(*, fixture_name, config): ... returning a scope string.","Ensure the function returns one of 'function','class','module','package','session'.","Catch/handle any internal errors inside the callable so it does not propagate.","Verify config option names exist (config.getoption) before accessing them inside the callable."],"exampleFix":"// before\n@pytest.fixture(scope=lambda name: 'session' if name == 'db' else 'function')\ndef db(): ...\n// after\ndef _scope(*, fixture_name, config):\n    return 'session' if fixture_name == 'db' else 'function'\n\n@pytest.fixture(scope=_scope)\ndef db(): ...","handlingStrategy":"type-guard","validationCode":"import inspect\ndef assert_scope_callable(fn):\n    sig = inspect.signature(fn)\n    params = {p.name: p.kind for p in sig.parameters.values()}\n    assert {'fixture_name','config'} <= set(params), 'scope callable must take fixture_name and config'\n    assert all(k == inspect.Parameter.KEYWORD_ONLY for k in params.values()), 'use keyword-only params'","typeGuard":"import inspect\nfrom typing import Callable\ndef is_valid_scope_callable(fn) -> bool:\n    try:\n        sig = inspect.signature(fn)\n    except (TypeError, ValueError):\n        return False\n    names = set(sig.parameters)\n    return {'fixture_name','config'} <= names","tryCatchPattern":null,"preventionTips":["Always define dynamic scope as def fn(*, fixture_name, config): ...","Unit-test the scope callable directly before wiring it to @pytest.fixture.","Validate return is one of the allowed scope strings."],"tags":["pytest","fixtures","scope","dynamic","signature"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}