pytest-dev/pytest · error · UsageError

Keyword expressions do not support call parameters.

Error message

Keyword expressions do not support call parameters.

What it means

In the keyword expression matcher (mark/__init__.py:208), __call__ rejects any keyword arguments because '-k' keyword expressions only support names and boolean operators, not function-call syntax like 'name(value)'. If kwargs are passed (e.g. the parsed expression contained a call), pytest raises UsageError('Keyword expressions do not support call parameters.') rather than silently misbehaving.

Solutions

  1. Use only names and boolean operators in -k: 'pytest -k "test_name and not slow"'.
  2. Use marks (@pytest.mark.smoke) and '-m smoke' if you need categorical filtering.
  3. Remove any '(...)' call syntax from the -k expression.

Example fix

// before
pytest -k "login(smoke)"
// after
pytest -k "login and smoke"
Defensive patterns

Strategy: validation

Validate before calling

import re
def validate_keyword_expr(expr: str) -> str:
    if re.search(r'\w+\s*\([^)]*\)', expr):
        raise ValueError("'-k' does not allow call syntax 'name(...)'; use names and and/or/not")
    return expr

Prevention

When it happens

Trigger: Writing 'pytest -k "test_name(smoke)"' or any '-k' expression using parentheses with arguments; a programmatically constructed MarkMatcher invoked with kwargs; a parsed expression tree that synthesizes a call node.

Common situations: Confusing '-k' (keyword filter) with '-m' (mark filter) syntax; attempting to pass parameters via the keyword expression; copy-pasting function-call syntax into the keyword argument.

Related errors


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

Appendix: source

Thrown at src/_pytest/mark/__init__.py:208

                continue
            mapped_names.add(node.name)

        # Add the names added as extra keywords to current or parent items.
        mapped_names.update(item.listextrakeywords())

        # Add the names attached to the current function through direct assignment.
        function_obj = getattr(item, "function", None)
        if function_obj:
            mapped_names.update(function_obj.__dict__)

        # Add the markers to the keywords as we no longer handle them correctly.
        mapped_names.update(mark.name for mark in item.iter_markers())

        return cls(mapped_names)

    def __call__(self, subname: str, /, **kwargs: str | int | bool | None) -> bool:
        if kwargs:
            raise UsageError("Keyword expressions do not support call parameters.")
        subname = subname.lower()
        return any(subname in name.lower() for name in self._names)


def deselect_by_keyword(items: list[Item], config: Config) -> None:
    keywordexpr = config.option.keyword.lstrip()
    if not keywordexpr:
        return

    expr = _parse_expression(keywordexpr, "Wrong expression passed to '-k'")

    remaining = []
    deselected = []
    for colitem in items:
        if not expr.evaluate(KeywordMatcher.from_item(colitem)):
            deselected.append(colitem)
        else:
            remaining.append(colitem)

View on GitHub (pinned to 0d6fbdeffa)