Repository: milvus-io/pymilvus

Issue:
`is_legal_ids()` rejects negative int64 primary keys
## Description

`is_legal_ids()` in `pymilvus/client/check.py` rejects negative int64 values, causing `search(ids=...)`, `get()`, and `query(ids=...)` to raise `ParamError` for valid INT64 primary keys. The Milvus server handles negative int64 PKs correctly, the rejection is purely client-side.

## Root Cause

`pymilvus/client/check.py` lines 133 and 145:

```python
if value < 0 or value > sys.maxsize:
    return False
```

INT64 primary keys span the full signed range `[-2^63, 2^63-1]`, but this check rejects `value < 0`, blocking half the valid key space.

## Reproduction

```python
from pymilvus import MilvusClient

client = MilvusClient(uri="...", token="...")

# Collection with INT64 PK containing negative IDs
negative_id = -2171431668238451468

# Works (server handles negative IDs fine):
client.query(collection_name="my_collection", filter=f"id == {negative_id}")

# Fails (client-side validation):
client.search(
    collection_name="my_collection",
    ids=[negative_id],
    limit=5,
    search_params={"metric_type": "COSINE"},
)
# ParamError: (code=1, message=`ids` value [..., -2171431668238451468, ...] is illegal)
```

## Expected Behavior

`is_legal_ids()` should accept any value in the signed int64 range `[-2^63, 2^63-1]`.

## Suggested Fix

```python
# Before (lines 133, 145):
if value < 0 or value > sys.maxsize:
    return False

# After:
if not (-(2**63) <= value <= 2**63 - 1):
    return False
```

I have a PR ready with the fix and tests.

## Environment

- pymilvus 2.6.8 (also affects 2.6.6, 2.6.7)
- Python 3.12
- Milvus/Zilliz Cloud server

Discussion:

Fix (patch):
diff --git a/pymilvus/client/check.py b/pymilvus/client/check.py
index 13bef6880..e96f817d7 100644
--- a/pymilvus/client/check.py
+++ b/pymilvus/client/check.py
@@ -1,5 +1,4 @@
 import datetime
-import sys
 from typing import Any, Callable, Union
 
 import numpy as np
@@ -11,6 +10,9 @@
 from . import entity_helper
 from .singleton_utils import Singleton
 
+_INT64_MIN = -(2**63)
+_INT64_MAX = 2**63 - 1
+
 
 def validate_strs(**kwargs):
     """validate if all values are legal non-emtpy str"""
@@ -130,7 +132,7 @@ def is_legal_ids(ids: Any) -> bool:
             if isinstance(i, bool) or not isinstance(i, (int, np.integer)):
                 return False
             value = int(i)
-            if value < 0 or value > sys.maxsize:
+            if not (_INT64_MIN <= value <= _INT64_MAX):
                 return False
         return True
 
@@ -142,7 +144,7 @@ def is_legal_ids(ids: Any) -> bool:
                 value = int(i)
             except (TypeError, ValueError, OverflowError):
                 continue
-            if value < 0 or value > sys.maxsize:
+            if not (_INT64_MIN <= value <= _INT64_MAX):
                 return False
         return True
 


Test changes:
diff --git a/tests/test_check.py b/tests/test_check.py
index 0d03227b1..15032f8fd 100644
--- a/tests/test_check.py
+++ b/tests/test_check.py
@@ -12,6 +12,7 @@
     check_pass_param,
     is_legal_address,
     is_legal_host,
+    is_legal_ids,
     is_legal_port,
 )
 from pymilvus.client.utils import (
@@ -86,6 +87,44 @@ def test_check_is_legal_port_false(self, invalid_port):
         assert valid is False
 
 
+class TestIsLegalIds:
+    @pytest.mark.parametrize(
+        "ids",
+        [
+            [1, 2, 3],
+            [0],
+            [-(2**63), 2**63 - 1],  # int64 min/max
+            [-1, -100, -9222883346732719253],  # negative int64 values
+            [np.int64(-1), np.int64(2**63 - 1)],
+        ],
+    )
+    def test_valid_int_ids(self, ids):
+        assert is_legal_ids(ids) is True
+
+    @pytest.mark.parametrize(
+        "ids",
+        [
+            ["abc", "def"],
+            ["-123", "456"],
+        ],
+    )
+    def test_valid_str_ids(self, ids):
+        assert is_legal_ids(ids) is True
+
+    @pytest.mark.parametrize(
+        "ids",
+        [
+            None,
+            [],
+            [True, False],
+            [2**63],  # exceeds int64 max
+            [-(2**63) - 1],  # exceeds int64 min
+        ],
+    )
+    def test_invalid_ids(self, ids):
+        assert is_legal_ids(ids) is False
+
+
 class TestCheckPassParam:
     def test_check_pass_param_valid(self):
         a = [[i * j for i in range(20)] for j in range(20)]