{"record":{"id":"eaa91dffd7062e31","repo":"pola-rs/polars","slug":"unsupported-operand-type-s-for-op-expr-sel","errorCode":null,"errorMessage":"unsupported operand type(s) for op: ('Expr' - 'Selector')","messagePattern":"unsupported operand type\\(s\\) for op: \\('Expr' - 'Selector'\\)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/selectors.py","lineNumber":524,"sourceCode":"        return self.as_expr().__ror__(other)\n\n    @overload\n    def __sub__(self, other: Selector) -> Selector: ...\n\n    @overload\n    def __sub__(self, other: Any) -> Expr: ...\n\n    def __sub__(self, other: Any) -> Selector | Expr:\n        if is_selector(other):\n            return Selector._from_pyselector(\n                PySelector.difference(self._pyselector, other._pyselector)\n            )\n        else:\n            return self.as_expr().__sub__(other)\n\n    def __rsub__(self, other: Any) -> NoReturn:\n        msg = \"unsupported operand type(s) for op: ('Expr' - 'Selector')\"\n        raise TypeError(msg)\n\n    @overload\n    def __xor__(self, other: Selector) -> Selector: ...\n\n    @overload\n    def __xor__(self, other: Any) -> Expr: ...\n\n    def __xor__(self, other: Any) -> Selector | Expr:\n        if is_column(other):  # @2.0: remove\n            other = by_name(other.meta.output_name())\n        if is_selector(other):\n            return Selector._from_pyselector(\n                PySelector.exclusive_or(self._pyselector, other._pyselector)\n            )\n        else:\n            return self.as_expr().__xor__(other)\n\n    def __rxor__(self, other: Any) -> Expr:","sourceCodeStart":506,"sourceCodeEnd":542,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/selectors.py#L506-L542","documentation":"Selector.__rsub__ always raises: `something - selector` where the left operand is not itself a selector (a scalar, numpy array, etc.) is rejected instead of being guessed as either set-difference or arithmetic subtraction with reflected operands.","triggerScenarios":"1 - cs.numeric() in select/with_columns; np_array - cs.all(); any expression where a Selector ends up on the right side of a minus with a non-selector left operand.","commonSituations":"Writing constant-minus-column expressions (deltas, inversions) with the selector on the right; vectorized numpy-style code pasted into polars expressions.","solutions":["Move the selector to the left for ARITHMETIC subtraction: cs.numeric() - 1 (Selector.__sub__ with a non-selector does expression arithmetic)","For constant-minus-column, convert the selector first: pl.lit(1) - cs.numeric().as_expr()","For set difference keep the selector left: cs.all() - cs.by_name('id')","Select the columns first, then operate on them in a subsequent step"],"exampleFix":"# before\ndf.select(1 - cs.numeric())\n\n# after\ndf.select(pl.lit(1) - cs.numeric().as_expr())\n# arithmetic with selector on the left also works:\ndf.select((cs.numeric() - 1).name.suffix('_dec'))","handlingStrategy":"type-guard","validationCode":"from polars.selectors import is_selector\nif is_selector(right) and not is_selector(left):\n    expr = pl.lit(left) - right.as_expr()  # never rely on `left - selector`","typeGuard":"from polars.selectors import is_selector\n\ndef safe_sub(left, right):\n    if is_selector(right):\n        return right.as_expr().__rsub__(left)\n    return left - right","tryCatchPattern":null,"preventionTips":["Keep selectors on the LEFT of arithmetic; they only support forward ops","Use .as_expr() to drop into normal expression algebra when reflection is needed"],"tags":["polars","selectors","operator-misuse","type-error"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}