{"record":{"id":"2a5c543b8a7324cf","repo":"MemPalace/mempalace","slug":"nin-requires-a-non-empty-list-for-field-r","errorCode":null,"errorMessage":"$nin requires a non-empty list for {field!r}","messagePattern":"\\$nin requires a non-empty list for (.+?)","errorType":"exception","errorClass":"UnsupportedFilterError","httpStatus":null,"severity":"error","filePath":"mempalace/backends/milvus.py","lineNumber":125,"sourceCode":"\n\ndef _translate_field(field: str, expected: Any) -> str:\n    field = _field_name(field)\n    if isinstance(expected, dict):\n        parts = []\n        for op, operand in expected.items():\n            if op == \"$eq\":\n                parts.append(f\"{field} == {_quote_value(operand)}\")\n            elif op == \"$ne\":\n                parts.append(f\"{field} != {_quote_value(operand)}\")\n            elif op == \"$in\":\n                if not isinstance(operand, list) or not operand:\n                    raise UnsupportedFilterError(f\"$in requires a non-empty list for {field!r}\")\n                items = \", \".join(_quote_value(item) for item in operand)\n                parts.append(f\"{field} in [{items}]\")\n            elif op == \"$nin\":\n                if not isinstance(operand, list) or not operand:\n                    raise UnsupportedFilterError(f\"$nin requires a non-empty list for {field!r}\")\n                items = \", \".join(_quote_value(item) for item in operand)\n                parts.append(f\"{field} not in [{items}]\")\n            elif op == \"$gt\":\n                parts.append(f\"{field} > {_quote_value(operand)}\")\n            elif op == \"$gte\":\n                parts.append(f\"{field} >= {_quote_value(operand)}\")\n            elif op == \"$lt\":\n                parts.append(f\"{field} < {_quote_value(operand)}\")\n            elif op == \"$lte\":\n                parts.append(f\"{field} <= {_quote_value(operand)}\")\n            elif op == \"$contains\":\n                parts.append(f\"{field} like {_like_value(operand)}\")\n            else:\n                raise UnsupportedFilterError(f\"operator {op!r} not supported by milvus\")\n        return \" and \".join(parts)\n    return f\"{field} == {_quote_value(expected)}\"\n\n","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/backends/milvus.py#L107-L143","documentation":"Raised in _translate_field() when the $nin operand is not a list or is empty — the mirror of the $in check. An empty 'not in' set is degenerate in Milvus filter syntax, so translation fails with UnsupportedFilterError before any request is made. Only $nin and $in have the list requirement; $eq/$ne accept scalars.","triggerScenarios":"where={\"wing\": {\"$nin\": []}}, where={\"room\": {\"$nin\": \"2024-01-01\"}} (scalar instead of list), or exclusion lists computed at runtime that end up empty.","commonSituations":"'Exclude these wings/rooms' filters where the exclusion set is data-driven and occasionally empty; porting Mongo queries where $nin: [] is accepted as 'match all'.","solutions":["Drop the $nin clause entirely when the exclusion list is empty — 'not in []' is equivalent to no filter","Wrap scalars into a list: {\"$nin\": [value]}","Guard with a builder that strips empty $nin keys before calling query"],"exampleFix":"// before\nwhere = {\"wing\": {\"$nin\": excluded}}  # excluded == []\ncollection.query(query_texts=[q], where=where)\n\n// after\nwhere = {\"wing\": {\"$nin\": excluded}} if excluded else None\ncollection.query(query_texts=[q], where=where)","handlingStrategy":"validation","validationCode":"def drop_empty_nin(where):\n    if not where:\n        return None\n    out = {}\n    for k, v in where.items():\n        if isinstance(v, dict):\n            if \"$nin\" in v and (not isinstance(v[\"$nin\"], list) or not v[\"$nin\"]):\n                v = {op: val for op, val in v.items() if op != \"$nin\"}\n                if not v:\n                    continue\n        out[k] = v\n    return out or None","typeGuard":null,"tryCatchPattern":"from mempalace.backends.base import UnsupportedFilterError\ntry:\n    collection.query(query_texts=[q], where=where, n_results=k)\nexcept UnsupportedFilterError as e:\n    if \"$nin\" in str(e):\n        where2 = {k: {op: val for op, val in v.items() if op != \"$nin\"} if isinstance(v, dict) else v for k, v in where.items()}\n        return collection.query(query_texts=[q], where=where2, n_results=k)\n    raise","preventionTips":["Treat empty exclusion lists as 'no filter'","Wrap scalars in lists when building $nin","Assert all $in/$nin operands are non-empty lists in debug builds"],"tags":["milvus","filter","nin-operator","validation"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}