hcengineering/platform · error

unknown predicate:

Error message

unknown predicate: 

What it means

createPredicates builds filter predicates from a $-keyed query object and looks each key up in the predicates table. If the key is not one of the supported predicates ($in, $all, $nin, $like, $regex, $gt, $gte, $lt, $lte, $exists, $ne, $size), it throws this error naming the first key of the object. It means the query used an unsupported or misspelled predicate.

Source

Thrown at foundations/core/packages/core/src/predicate.ts:156

        return false
      })
  }
}

export function isPredicate (o: Record<string, any>): boolean {
  if (o === null || typeof o !== 'object') {
    return false
  }
  const keys = Object.keys(o)
  return keys.length > 0 && keys.every((key) => key.startsWith('$'))
}

export function createPredicates (o: Record<string, any>, propertyKey: string): Predicate[] {
  const keys = Object.keys(o)
  const result: Predicate[] = []
  for (const key of keys) {
    const factory = predicates[key]
    if (factory === undefined) throw new Error('unknown predicate: ' + keys[0])
    result.push(factory(o[key], propertyKey))
  }
  return result
}

View on GitHub (pinned to 63e28dc964)

Solutions

  1. Use only the supported predicates listed in predicate.ts ($in, $all, $nin, $like, $regex, $gt, $gte, $lt, $lte, $exists, $ne, $size).
  2. Fix the misspelled predicate name — note the message reports keys[0], so verify the first $-key of the object.
  3. Emulate unsupported operators client-side: fetch with supported predicates then filter in code.
  4. Validate user-supplied filters against an allow-list of predicate names before calling find().

Example fix

// before
find(docClass, { name: { $contains: 'foo' } })
// after
find(docClass, { name: { $like: '%foo%' } })
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED_PREDICATES = ['$in', '$all', '$nin', '$like', '$regex', '$gt', '$gte', '$lt', '$lte', '$exists', '$ne', '$size']
function validateFilter(filter: Record<string, Record<string, any>>): void {
  for (const [field, preds] of Object.entries(filter)) {
    for (const key of Object.keys(preds)) {
      if (!SUPPORTED_PREDICATES.includes(key)) {
        throw new Error(`unsupported predicate ${key} on field ${field}`)
      }
    }
  }
}

Type guard

function hasOnlyKnownPredicates(o: Record<string, any>, known: string[]): boolean {
  return isPredicate(o) && Object.keys(o).every((k) => known.includes(k))
}

Try / catch

try {
  return await find(clazz, filter)
} catch (e) {
  if (e instanceof Error && e.message.startsWith('unknown predicate:')) {
    const op = e.message.split('unknown predicate: ')[1]
    console.error(`Filter uses unsupported predicate "${op}"; supported: $in $all $nin $like $regex $gt $gte $lt $lte $exists $ne $size`)
  }
  throw e
}

Prevention

When it happens

Trigger: Queries like { name: { $contains: 'x' } } or { age: { $elemMatch: {...} } } (Mongo operators not implemented here), typos such as { $gte : ... } vs { $gtes: ... }, or nested objects mistakenly treated as predicates because all their keys start with '$'.

Common situations: Porting MongoDB queries assuming full operator coverage; typos; dynamic query builders emitting unsupported keys; passing user-supplied filter JSON directly into find().

Related errors


AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29). Data as JSON: /api/errors/79f1f37bb71c1f22. Report an issue: GitHub.