pytest-dev/pytest · error · SyntaxError
unexpected character
Error message
unexpected character "{input[pos]}" What it means
A SyntaxError raised by the marker-expression tokenizer when the current character matches none of the recognized token starts (whitespace, parens, =, comma, quote, or the identifier/number regex). The unexpected character and its 1-based column are reported. It is the catch-all lexical error for anything the grammar cannot start to tokenize.
Solutions
- Read the reported character and column; remove or replace it.
- Restrict marker expressions to identifiers, `and`, `or`, `not`, parentheses, and (for kwargs) `name=value` literals.
- If you need richer filtering, write a conftest hook (pytest_collection_modifyitems) instead of a CLI expression.
Example fix
# before pytest -m '@smoke' # after pytest -m 'smoke'
Defensive patterns
Strategy: validation
Validate before calling
import re
VALID_EXPR_CHARS = re.compile(r"^[\w\s()=,.'\"]+$")
def looks_like_marker_expr(s: str) -> bool:
return bool(VALID_EXPR_CHARS.match(s)) Try / catch
try:
Expression.compile(expr)
except SyntaxError as e:
# surface the unexpected character to the user
... Prevention
- Restrict marker expressions to identifier and operator characters.
- Do not paste arbitrary Python expressions into -m/-k.
- Validate user-supplied filter strings before running pytest.
When it happens
Trigger: Expressions containing characters like `@`, `#`, `$`, `%`, `;`, or unicode symbols that are not part of identifier/number/keyword grammar. For example `-m '@smoke'`, `-k 'test_##'`, or `-m 'a;b'`.
Common situations: Pasting a Python expression into -m expecting full Python syntax; using decorator-style or comment characters; locale/keyboard producing unexpected symbols.
Related errors
- closing quote " " is missing
- escaping with "\" not supported in marker expression
- : : at column
- expected ; got
- not a valid python identifier
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/de9a487940d93909.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/mark/expression.py:126
(FILE_NAME, 1, pos + backslash_pos + 1, input),
)
yield Token(TokenType.STRING, value, pos)
pos += len(value)
else:
match = re.match(r"(:?\w|:|\+|-|\.|\[|\]|\\|/)+", input[pos:])
if match:
value = match.group(0)
if value == "or":
yield Token(TokenType.OR, value, pos)
elif value == "and":
yield Token(TokenType.AND, value, pos)
elif value == "not":
yield Token(TokenType.NOT, value, pos)
else:
yield Token(TokenType.IDENT, value, pos)
pos += len(value)
else:
raise SyntaxError(
f'unexpected character "{input[pos]}"',
(FILE_NAME, 1, pos + 1, input),
)
yield Token(TokenType.EOF, "", pos)
@overload
def accept(self, type: TokenType, *, reject: Literal[True]) -> Token: ...
@overload
def accept(
self, type: TokenType, *, reject: Literal[False] = False
) -> Token | None: ...
def accept(self, type: TokenType, *, reject: bool = False) -> Token | None:
if self.current.type is type:
token = self.current
if token.type is not TokenType.EOF:
self.current = next(self.tokens)View on GitHub (pinned to 0d6fbdeffa)