{"record":{"id":"ce5e91378a2e9399","repo":"pathwaycom/pathway","slug":"filter-argument-of-table-filter-has-to-be-bool","errorCode":null,"errorMessage":"Filter argument of Table.filter() has to be bool, found {filter_type}.","messagePattern":"Filter argument of Table\\.filter\\(\\) has to be bool, found (.+?)\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/pathway/internals/table.py","lineNumber":523,"sourceCode":"            Table: Result has the same schema as `self` and its ids are subset of `self.id`.\n\n\n        Example:\n\n        >>> import pathway as pw\n        >>> vertices = pw.debug.table_from_markdown('''\n        ... label outdegree\n        ...     1         3\n        ...     7         0\n        ... ''')\n        >>> filtered = vertices.filter(vertices.outdegree == 0)\n        >>> pw.debug.compute_and_print(filtered, include_id=False)\n        label | outdegree\n        7     | 0\n        \"\"\"\n        filter_type = self.eval_type(filter_expression)\n        if filter_type != dt.BOOL:\n            raise TypeError(\n                f\"Filter argument of Table.filter() has to be bool, found {filter_type}.\"\n            )\n        ret = self._filter(filter_expression)\n        if (\n            filter_col := expr.get_column_filtered_by_is_none(filter_expression)\n        ) is not None and filter_col.table == self:\n            name = filter_col.name\n            dtype = self._columns[name].dtype\n            ret = ret.update_types(**{name: dt.unoptionalize(dtype)})\n        return ret\n\n    @trace_user_frame\n    @desugar\n    @check_arg_types\n    def split(\n        self, split_expression: expr.ColumnExpression\n    ) -> tuple[Table[TSchema], Table[TSchema]]:\n        \"\"\"Split a table according to `split_expression` condition.","sourceCodeStart":505,"sourceCodeEnd":541,"githubUrl":"https://github.com/pathwaycom/pathway/blob/fa2f74a4649b7c5908690cf60137263d8d80de5f/python/pathway/internals/table.py#L505-L541","documentation":"Table.filter() evaluates the static type of filter_expression with eval_type and requires exactly dt.BOOL. Anything else — Optional[bool], int, string, or any non-boolean expression — raises TypeError naming the found type. This catches filtering on a nullable boolean column or passing a truthy non-bool expression.","triggerScenarios":"t.filter(t.flag) where flag is Optional[bool] (schema bool | None); t.filter(t.count) (int column); t.filter(t.name) (string); filtering on a column produced by an expression whose dtype is not exactly bool.","commonSituations":"Optional columns from connectors with missing values; porting pandas-style boolean masking where any truthy column works; using counts or comparisons-of-None as predicates.","solutions":["Make the predicate explicitly boolean: t.filter(t.flag == True) or t.filter(t.flag.fill(True)) for Optional[bool]","Combine null-safety: t.filter(t.flag.is_not_none() & t.flag.fill(False))","Check the column dtype with t.schema / t['col'].dtype and fix the expression until it evaluates to bool"],"exampleFix":"# before\nt.filter(t.flag)  # flag: Optional[bool] -> TypeError\n\n# after\nt.filter(t.flag.fill(False))\n# or\nt.filter(t.flag == True)","handlingStrategy":"type-guard","validationCode":"def filter_is_bool(table, expression) -> bool:\n    return table.eval_type(expression) == pw.dtype(bool) if hasattr(pw, 'dtype') else table.eval_type(expression).__class__.__name__ == 'BOOL'","typeGuard":"import pathway as pw\n\ndef is_bool_predicate(table: pw.Table, expr) -> bool:\n    from pathway.internals import dtypes as dt\n    return table.eval_type(expr) == dt.BOOL","tryCatchPattern":null,"preventionTips":["Always write explicit boolean predicates (comparisons, == True, fill())","Inspect column dtypes in the schema for Optional[bool] before filtering"],"tags":["type-check","filter","pathway"],"backgroundTag":null,"analyzedSha":"fa2f74a4649b7c5908690cf60137263d8d80de5f","analyzedAt":"2026-08-15T01:48:17.006Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}