{"record":{"id":"4791c2e380ce4995","repo":"apache/superset","slug":"operator-operator-enum-value-is-not-supported","errorCode":null,"errorMessage":"Operator '{operator_enum.value}' is not supported on relationship column '{col_name}'. Use one of: eq, ne, in, nin, is_null, is_not_null.","messagePattern":"Operator '(.+?)' is not supported on relationship column '(.+?)'\\. Use one of: eq, ne, in, nin, is_null, is_not_null\\.","errorType":"validation","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"superset/daos/base.py","lineNumber":701,"sourceCode":"                    f\"{type(value).__name__}. Use '{counterpart}' to match \"\n                    f\"multiple related ids.\"\n                )\n            if operator_enum == ColumnOperatorEnum.eq:\n                return query.filter(column.any(related_pk == value))\n            return query.filter(~column.any(related_pk == value))\n        if operator_enum == ColumnOperatorEnum.in_:\n            values = value if isinstance(value, (list, tuple)) else [value]\n            return query.filter(column.any(related_pk.in_(values)))\n        if operator_enum == ColumnOperatorEnum.nin:\n            values = value if isinstance(value, (list, tuple)) else [value]\n            return query.filter(~column.any(related_pk.in_(values)))\n        if operator_enum == ColumnOperatorEnum.is_null:\n            # \"has no related rows at all\"\n            return query.filter(~column.any())\n        if operator_enum == ColumnOperatorEnum.is_not_null:\n            # \"has at least one related row\"\n            return query.filter(column.any())\n        raise ValueError(\n            f\"Operator '{operator_enum.value}' is not supported on \"\n            f\"relationship column '{col_name}'. Use one of: eq, ne, in, \"\n            f\"nin, is_null, is_not_null.\"\n        )\n\n    @classmethod\n    def get_filterable_columns_and_operators(cls) -> Dict[str, List[str]]:\n        \"\"\"\n        Returns a dict mapping filterable columns (including hybrid/computed fields if\n        present) to their supported operators. Used by MCP tools to dynamically expose\n        filter options. Custom fields supported by the DAO but not present on the model\n        should be documented here.\n        \"\"\"\n\n        mapper = inspect(cls.model_cls)\n        columns = {c.key: c for c in mapper.columns}\n        # Collection relationships (m2m / one-to-many) are filterable via\n        # `.any()` against the related model's primary key. Only advertise","sourceCodeStart":683,"sourceCodeEnd":719,"githubUrl":"https://github.com/apache/superset/blob/f4587218dd19d046c3e4d00063e7d27f8a2ed354/superset/daos/base.py#L683-L719","documentation":"Terminal ValueError from BaseDAO._apply_relationship_filter(): the operator supplied for a collection relationship is not one of eq, ne, in, nin, is_null, is_not_null. Scalar-oriented operators (sw, ew, like, gt, lt, ge, le, etc.) don't make sense on a collection of related rows, so they are rejected with an explicit message instead of producing a cryptic SQLAlchemy error at query time.","triggerScenarios":"filters=[{\"col\": \"<uselist relationship>\", \"opr\": \"like\"|\"sw\"|\"gt\"|..., \"value\": ...}] passed to any DAO find/list call.","commonSituations":"Generic filter builders (API clients, MCP tools) applying the full ColumnOperatorEnum set uniformly to every column without distinguishing relationships from scalar columns.","solutions":["Restrict relationship filters to eq/ne/in/nin/is_null/is_not_null (the error message lists them).","To filter by a related model's text field, query that model's DAO directly instead of through the relationship.","Fetch get_filterable_columns_and_operators() and honor the per-column operator list it advertises."],"exampleFix":"# before\nfilters=[{\"col\": \"editors\", \"opr\": \"like\", \"value\": \"bob\"}]\n\n# after\nfilters=[{\"col\": \"editors\", \"opr\": \"is_not_null\"}]  # or filter the related model's DAO directly","handlingStrategy":"validation","validationCode":"SUPPORTED_REL_OPS = {\"eq\", \"ne\", \"in\", \"nin\", \"is_null\", \"is_not_null\"}\n\ndef relationship_filters_valid(filters) -> bool:\n    return all(f.get(\"opr\") in SUPPORTED_REL_OPS for f in filters or [])","typeGuard":"def is_supported_rel_op(opr: str) -> bool:\n    return opr in {\"eq\", \"ne\", \"in\", \"nin\", \"is_null\", \"is_not_null\"}","tryCatchPattern":"try:\n    dao.find(query=\", filters=filters)\nexcept ValueError as ex:\n    if 'not supported on relationship column' in str(ex):\n        # drop or rewrite the offending operator, then retry\n        ...","preventionTips":["Treat relationship columns as a distinct filter class in client code with its own operator whitelist.","For text searches on related entities, query the related DAO directly.","Encode the operator whitelist from the DAO's filterable-columns metadata, not from memory."],"tags":["dao","filters","relationships","operators"],"backgroundTag":null,"analyzedSha":"f4587218dd19d046c3e4d00063e7d27f8a2ed354","analyzedAt":"2026-08-14T22:39:27.425Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}