mastra-ai/mastra · error

validation.messages.join(', ')

Error message

validation.messages.join(', ')

What it means

`validateFilter` runs the vector-store adapter's `validateFilterSupport` check before translating a filter; when the adapter reports `supported: false`, it throws an error whose message is all unsupported-feature messages joined with ', '. This surfaces, per vector DB, which filter operators/structures (e.g. `$regex`, nested logical groups, `$elemMatch`) the backend does not implement.

Source

Thrown at packages/core/src/vector/filter/base.ts:293

    NOT_REQUIRES_OBJECT: `$not operator requires an object`,
    NOT_CANNOT_BE_EMPTY: `$not operator cannot be empty`,
    INVALID_LOGICAL_OPERATOR_CONTENT: (path: string) =>
      `Logical operators must contain field conditions, not direct operators: ${path}`,
    INVALID_TOP_LEVEL_OPERATOR: (op: string) => `Invalid top-level operator: ${op}`,
    ELEM_MATCH_REQUIRES_OBJECT: `$elemMatch requires an object with conditions`,
  } as const;

  /**
   * Helper to handle array value normalization consistently
   */
  protected normalizeArrayValues(values: any[]): any[] {
    return values.map(value => this.normalizeComparisonValue(value));
  }

  protected validateFilter(filter: Filter): void {
    const validation = this.validateFilterSupport(filter);
    if (!validation.supported) {
      throw new Error(validation.messages.join(', '));
    }
  }

  /**
   * Validates if a filter structure is supported by the specific vector DB
   * and returns detailed validation information.
   */
  private validateFilterSupport(
    node: Filter,
    path: string = '',
  ): {
    supported: boolean;
    messages: string[];
  } {
    const messages: string[] = [];

    // Handle primitives and empty values
    if (this.isPrimitive(node) || this.isEmpty(node)) {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Read the joined messages — they enumerate exactly which operators/structures are unsupported; remove or rewrite those filter parts.
  2. Simplify the filter to the adapter's supported subset (e.g. replace `$not` with explicit complement conditions).
  3. Do client-side filtering: fetch with supported filter conditions, then apply the unsupported predicate in JS after results return.
  4. Switch to a vector store adapter that supports the filter features you need, or check the adapter docs for its filter capability matrix.

Example fix

// before
await store.query({ filter: { $not: { status: 'draft' } } }); // unsupported
// after
await store.query({ filter: { status: { $ne: 'draft' } } }); // or filter results in JS
Defensive patterns

Strategy: fallback

Validate before calling

const UNSUPPORTED = [/\$not/, /\$elemMatch/, /\$regex/]; // adjust per adapter
function assertFilterSupported(filter: Record<string, unknown>) {
  for (const key of Object.keys(filter)) {
    if (UNSUPPORTED.some(re => re.test(key))) throw new Error(`Operator ${key} unsupported by this vector store`);
  }
}

Type guard

function usesOnlySupportedOps(filter: Record<string, unknown>, allowed: string[]): boolean {
  return Object.keys(filter).every(k => allowed.includes(k) || k === 'id');
}

Try / catch

try {
  results = await store.query({ index, filter });
} catch (e) {
  if (e instanceof Error && /not supported|unsupported/i.test(e.message)) {
    results = (await store.query({ index })).filter(postFilterInJs);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `vector.query(...)`/`translate(filter)` (or storage-backed memory queries) with a filter using operators the chosen adapter doesn't support — e.g. `$not` or `$elemMatch` on a backend lacking them, or mixing top-level operators unsupported by pgvector/MongoDB/other adapters.

Common situations: Porting code between vector stores (Mongo -> pgvector) and reusing filter shapes; LLM-generated filters including fancy operators; docs examples copied across adapters.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/7a5b7a365ff38a33. Report an issue: GitHub.