{"id":"27783714a895dcad","repo":"pytest-dev/pytest","slug":"unexpected-character-s-value-token-value","errorCode":null,"errorMessage":"unexpected character/s \"{value_token.value}\"","messagePattern":"unexpected character/s \"(.+?)\"","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"src/_pytest/mark/expression.py","lineNumber":239,"sourceCode":"    if keyword.iskeyword(keyword_name.value):\n        raise SyntaxError(\n            f\"unexpected reserved python keyword `{keyword_name.value}`\",\n            (FILE_NAME, 1, keyword_name.pos + 1, s.input),\n        )\n    s.accept(TokenType.EQUAL, reject=True)\n\n    if value_token := s.accept(TokenType.STRING):\n        value: str | int | bool | None = value_token.value[1:-1]  # strip quotes\n    else:\n        value_token = s.accept(TokenType.IDENT, reject=True)\n        if (number := value_token.value).isdigit() or (\n            number.startswith(\"-\") and number[1:].isdigit()\n        ):\n            value = int(number)\n        elif value_token.value in BUILTIN_MATCHERS:\n            value = BUILTIN_MATCHERS[value_token.value]\n        else:\n            raise SyntaxError(\n                f'unexpected character/s \"{value_token.value}\"',\n                (FILE_NAME, 1, value_token.pos + 1, s.input),\n            )\n\n    ret = ast.keyword(keyword_name.value, ast.Constant(value))\n    return ret\n\n\ndef all_kwargs(s: Scanner) -> list[ast.keyword]:\n    ret = [single_kwarg(s)]\n    while s.accept(TokenType.COMMA):\n        ret.append(single_kwarg(s))\n    return ret\n\n\nclass ExpressionMatcher(Protocol):\n    \"\"\"A callable which, given an identifier and optional kwargs, should return\n    whether it matches in an :class:`Expression` evaluation.","sourceCodeStart":221,"sourceCodeEnd":257,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/mark/expression.py#L221-L257","documentation":"In `ident(name=value)` the value must be a quoted string, an integer literal, or one of `True`/`False`/`None`. If the value token is an unquoted identifier (or any token that is none of those), this SyntaxError is raised at the value's column. Marker kwarg values are literals, not references to other markers.","triggerScenarios":"`foo(x=bar)` where `bar` is unquoted, or `foo(x=1.5)` (floats are not allowed), or `foo(x=-)`.","commonSituations":"Assuming kwarg values can reference other markers/variables; pasting enum names or floats as values.","solutions":["Quote string values: `foo(x=\"bar\")`.","Use integer literals (`foo(x=5)`, `foo(x=-3)`) or the booleans/None builtins only.","For floats or symbolic references, encode them as strings and decode in your matcher."],"exampleFix":"# before\npytest -m 'config(env=prod)'\n# after\npytest -m 'config(env=\"prod\")'","handlingStrategy":"validation","validationCode":"def kwarg_value_ok(v: str) -> bool:\n    if v in ('True', 'False', 'None'):\n        return True\n    digits = v.lstrip('-')\n    if digits.isdigit():\n        return True\n    return len(v) >= 2 and v[0] == v[-1] and v[0] in (chr(39), chr(34))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always quote string values.","Encode floats/symbols as quoted strings and decode in the matcher."],"tags":["pytest","marker-expression","kwargs","invalid-value"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}