jd-opensource/joyagent-jdgenie · error · ValueError

❌ 不支持的过滤值类型: ,字段

Error message

❌ 不支持的过滤值类型: {type(val)},字段: {key}

What it means

QdrantUtils.delete builds a Filter from a filters dict and raises ValueError when a field's value is of an unsupported type for the condition builder. Supported shapes are match-style values and range dicts ({"gte":..,"lte":..}); anything else (nested dict without range ops, list, None value) is rejected.

Solutions

  1. Convert list values to explicit must/should match conditions (one FieldCondition per element) before calling delete
  2. Use only scalars for equality: filters={"status": "old"} instead of filters={"status": ["a","b"]}
  3. For numeric comparisons use the range dict form: filters={"created_at": {"gte": 1700000000, "lte": 1800000000}}
  4. Extend the filter builder to handle the unsupported type instead of raising, if lists are a legitimate use case

Example fix

// before
qdrant.delete(filters={"category": ["a", "b"]})  # ValueError: 不支持的过滤值类型: list
// after
for cat in ["a", "b"]:
    qdrant.delete(filters={"category": cat})
Defensive patterns

Strategy: type-guard

Validate before calling

RANGE_OPS = {'gte','lte','gt','lt'}
def delete_filters_supported(filters):
    for key, val in (filters or {}).items():
        if isinstance(val, dict):
            if not (set(val) & RANGE_OPS):
                return False, f'{key}: dict without range ops'
        elif not isinstance(val, (str, int, float, bool)):
            return False, f'{key}: {type(val).__name__} unsupported'
    return True, None

Type guard

def is_scalar_or_range(v):
    return isinstance(v, (str, int, float, bool)) or (isinstance(v, dict) and any(k in v for k in ('gte','lte','gt','lt')))

Try / catch

try:
    qdrant.delete(filters=filters)
except ValueError as e:
    logger.error('unsupported filter shape: %s', e)
    # fall back to per-scalar deletes or fix the filter

Prevention

When it happens

Trigger: delete(filters={...}) where some field value is not a scalar (str/int/float/bool) and not a dict containing range operators like gte/lte/gt/lt — e.g. filters={"tags": ["a","b"]} (list) or a nested dict of unsupported structure.

Common situations: Passing SQL/elastic-style query dicts into Qdrant filters; assuming list values mean 'match any'; a shared filter-building helper used by search() reused with wrong value shapes; schema drift where a field became an array in stored payloads.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08). Data as JSON: /api/errors/c91f856173369fe0. Report an issue: GitHub.

Appendix: source

Thrown at genie-tool/genie_tool/util/qdrant_utils.py:198

            for key, val in filters.items():
                if isinstance(val, (str, bool, int, float)):
                    must_conditions.append(
                        FieldCondition(key=key, match=MatchValue(value=val))
                    )
                elif isinstance(val, list):
                    must_conditions.append(
                        FieldCondition(key=key, match=MatchAny(any=val))
                    )
                elif isinstance(val, dict):
                    range_args = {}
                    for op in ["gte", "gt", "lte", "lt"]:
                        if op in val:
                            range_args[op] = val[op]
                    must_conditions.append(
                        FieldCondition(key=key, range=Range(**range_args))
                    )
                else:
                    raise ValueError(f"❌ 不支持的过滤值类型: {type(val)},字段: {key}")
            
            query_filter = Filter(must=must_conditions) if must_conditions else None
            
            delete_request = self.client.delete(
            collection_name=self.collection_name,
            points_selector=query_filter  # 👈 旧版也支持
        )
        
        return self.client.delete(collection_name=self.collection_name, points_selector=delete_request)
    
    def search(self, query_vector, filters):
        must_conditions = []
        
        for key, val in filters.items():
            if isinstance(val, (str, bool, int, float)):
                must_conditions.append(
                    FieldCondition(
                        key=key,

View on GitHub (pinned to 2417e0b8b6)