microsoft/semantic-kernel · error · VectorStoreOperationException

Error running filter

Error message

Error running filter: {e}

What it means

Thrown by InMemoryCollection._run_filter (in_memory.py:861), wrapping any exception raised while executing a validated filter callable against a record. The original exception is chained (from e). This indicates the filter passed validation but failed at evaluation time, almost always due to record shape mismatch.

Solutions

  1. Guard attribute access in the filter: "lambda x: getattr(x, 'age', None) is not None and x.age > 18" (getattr is not in the allowlist, so use a callable filter or ensure the field exists).
  2. Normalize records so the filtered field always exists with a consistent type before search.
  3. Catch VectorStoreOperationException and inspect the chained __cause__ to see the underlying AttributeError/TypeError.
  4. Validate the record schema against the filter expression in a dry-run before issuing the search.

Example fix

# before
filter = "lambda x: x.age > 18"  # fails on records missing 'age'

# after (callable with safe access)
filter = lambda r: r.get('age') is not None and r['age'] > 18
Defensive patterns

Strategy: try-catch

Validate before calling

# dry-run the filter against a sample record before searching
def filter_dry_runs(filter_str: str, sample_record: dict) -> bool:
    from semantic_kernel.connectors.in_memory import InMemoryCollection
    # parse using the same validator, then evaluate on the sample
    coll = InMemoryCollection(...)
    fn = coll._parse_and_validate_filter(filter_str)
    try:
        return coll._run_filter(fn, sample_record)
    except Exception:
        return False

Type guard

def record_has_fields(record: dict, fields: list[str]) -> bool:
    return all(f in record and record[f] is not None for f in fields)

Try / catch

from semantic_kernel.exceptions.vector_store_exceptions import VectorStoreOperationException

try:
    results = await collection.search(options)
except VectorStoreOperationException as ex:
    cause = ex.__cause__
    # cause is usually AttributeError/KeyError/TypeError from record-shape mismatch
    if isinstance(cause, (KeyError, AttributeError)):
        options = VectorSearchOptions(filter=lambda x: x.get('age') is not None and x['age'] > 18)

Prevention

When it happens

Trigger: The filter accesses a field that does not exist on a record (AttributeError/KeyError), applies an operator to incompatible types (TypeError), or calls an allowed function with bad arguments. Example: "lambda x: x.age > 18" evaluated against a record with no 'age' key.

Common situations: Heterogeneous records where some lack the filtered field; schema drift between filter and data; numeric vs string comparison; None values in a comparison; renamed fields.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/6373441ac6ee2c8d. Report an issue: GitHub.

Appendix: source

Thrown at python/semantic_kernel/connectors/in_memory.py:861

        def filter_callable(*args: Any) -> Any:
            if len(args) != len(lambda_param_order):
                raise VectorStoreOperationException(
                    f"Filter expected {len(lambda_param_order)} argument(s), but received {len(args)}."
                )
            context = {
                name: ReadOnlyAttributeDict._wrap_value(value)
                for name, value in zip(lambda_param_order, args, strict=True)
            }
            return evaluator.evaluate(lambda_node.body, context)

        return filter_callable

    def _run_filter(self, filter: Callable, record: AttributeDict[TAKey, TAValue]) -> bool:
        """Run the filter on the record, supporting attribute access."""
        try:
            return filter(ReadOnlyAttributeDict(record))
        except Exception as e:
            raise VectorStoreOperationException(f"Error running filter: {e}") from e

    @override
    def _lambda_parser(self, node: ast.AST) -> Any:
        """Not used by InMemoryCollection, but required by the interface."""
        pass

    def _calculate_vector_similarity(
        self,
        search_vector: Sequence[float | int],
        record_vector: Sequence[float | int],
        distance_func: Callable,
        invert_score: bool = False,
    ) -> float:
        calc = distance_func(record_vector, search_vector)
        if invert_score:
            return 1.0 - float(calc)
        return float(calc)

View on GitHub (pinned to c028a0c7dc)