{"record":{"id":"d9e047b201fa28b2","repo":"pandas-dev/pandas","slug":"invalid-unary-operator-op-r-valid-operators-are","errorCode":null,"errorMessage":"Invalid unary operator {op!r}, valid operators are {UNARY_OPS_SYMS}","messagePattern":"Invalid unary operator (.+?), valid operators are (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/computation/ops.py","lineNumber":519,"sourceCode":"    op : str\n        The token used to represent the operator.\n    operand : Term or Op\n        The Term or Op operand to the operator.\n\n    Raises\n    ------\n    ValueError\n        * If no function associated with the passed operator token is found.\n    \"\"\"\n\n    def __init__(self, op: Literal[\"+\", \"-\", \"~\", \"not\"], operand) -> None:\n        super().__init__(op, (operand,))\n        self.operand = operand\n\n        try:\n            self.func = _unary_ops_dict[op]\n        except KeyError as err:\n            raise ValueError(\n                f\"Invalid unary operator {op!r}, valid operators are {UNARY_OPS_SYMS}\"\n            ) from err\n\n    def __call__(self, env) -> MathCall:\n        operand = self.operand(env)\n        # error: Cannot call function of unknown type\n        return self.func(operand)  # type: ignore[operator]\n\n    def __repr__(self) -> str:\n        return pprint_thing(f\"{self.op}({self.operand})\")\n\n    @property\n    def return_type(self) -> np.dtype:\n        operand = self.operand\n        if operand.return_type == np.dtype(\"bool\"):\n            return np.dtype(\"bool\")\n        if isinstance(operand, Op) and (\n            operand.op in _cmp_ops_dict or operand.op in _bool_ops_dict","sourceCodeStart":501,"sourceCodeEnd":537,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/computation/ops.py#L501-L537","documentation":"Raised by UnaryOp.__init__ in pandas.core.computation.ops when the operator token is not in _unary_ops_dict, whose keys are UNARY_OPS_SYMS = ('+','-','~','not'). It is a ValueError chained from the underlying KeyError. Because the AST tokenizer only ever produces these four unary forms, this is effectively an internal invariant guard rather than something reachable from a normal pd.eval/df.query string.","triggerScenarios":"Constructing ops.UnaryOp directly with an unsupported token (e.g. UnaryOp('!', term)), or a custom engine emitting an exotic unary token. Public eval expressions cannot reach this path because the parser would have rejected the token at parse time.","commonSituations":"Third-party libraries or experimental code that builds Op trees by hand; users assuming C/JS-style '!' or 'not()' syntax is honored. Python's `not` IS supported, but '!' is not.","solutions":["Only use '+', '-', '~', or 'not' as unary operators in eval expressions.","Replace '!' with 'not ' (e.g. pd.eval('not (a > 0)')).","If calling UnaryOp directly, validate the token against UNARY_OPS_SYMS before constructing."],"exampleFix":"# before\nfrom pandas.core.computation.ops import UnaryOp, Term\nUnaryOp('!', term)  # ValueError\n\n# after (in an expression)\nimport pandas as pd\npd.eval('not (a > 0)')   # use Python 'not'\n# after (bitwise NOT on integers/bools)\npd.eval('~b')            # b must be bool or int","handlingStrategy":"validation","validationCode":"from pandas.core.computation.ops import UNARY_OPS_SYMS\n\ndef assert_unary_op(op: str) -> str:\n    if op not in UNARY_OPS_SYMS:\n        raise ValueError(f'{op!r} not a valid unary op; use {UNARY_OPS_SYMS}')\n    return op","typeGuard":"from pandas.core.computation.ops import UNARY_OPS_SYMS\n\ndef is_supported_unary_op(op: str) -> bool:\n    return op in UNARY_OPS_SYMS\n","tryCatchPattern":"try:\n    UnaryOp(op, operand)\nexcept ValueError as e:\n    if 'Invalid unary operator' in str(e):\n        # remap to a supported token or skip eval\n        ...\n    raise","preventionTips":["Use only '+', '-', '~', 'not' as unary operators in expressions.","Replace '!' with 'not'.","Avoid constructing UnaryOp manually."],"tags":["pandas","eval","operators","unary","internal"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}