remix-run/remix · error · Error

Unsupported predicate

Error message

Unsupported predicate

What it means

Thrown by the MySQL SQL compiler when a predicate object passed to where/having/on does not match any known predicate type (comparison, logical combination like and/or, etc.). The compiler exhaustively switches over predicate shapes and this is the fallback for unrecognized `type` values. It almost always indicates a malformed or hand-constructed predicate object rather than one built by the library's query builder.

Source

Thrown at packages/data-table-mysql/src/lib/sql-compiler.ts:405

  if (predicate.type === 'null') {
    return (
      quotePath(predicate.column) + (predicate.operator === 'isNull' ? ' is null' : ' is not null')
    )
  }

  if (predicate.type === 'logical') {
    if (predicate.predicates.length === 0) {
      return predicate.operator === 'and' ? '1 = 1' : '1 = 0'
    }

    let joiner = predicate.operator === 'and' ? ' and ' : ' or '

    return predicate.predicates
      .map((child) => '(' + compilePredicate(child, context) + ')')
      .join(joiner)
  }

  throw new Error('Unsupported predicate')
}

function compileComparisonValue(
  predicate: Extract<Predicate, { type: 'comparison' }>,
  context: CompileContext,
): string {
  if (predicate.valueType === 'column') {
    return quotePath(predicate.value)
  }

  return pushValue(context, predicate.value)
}

function normalizeJoinType(type: string): string {
  return normalizeJoinTypeHelper(type)
}

function quoteIdentifier(value: string): string {

View on GitHub (pinned to 9696913134)

Solutions

  1. Build predicates with the library's own builder functions (e.g. eq/and/or helpers) instead of plain object literals
  2. Check the predicate's `type` field at runtime and log the offending object to find the malformed value
  3. Ensure all @remix-run/data-table* packages are on the same version (align versions in package.json and reinstall)
  4. If deserializing predicates, validate the reconstructed shape before passing to where/having

Example fix

// before
table.select().where({ type: 'comparision', column: 'id', op: '=', value: 1 } as any)

// after
import { eq } from 'remix/data-table'
table.select().where(eq('id', 1))
Defensive patterns

Strategy: validation

Validate before calling

const PREDICATE_TYPES = new Set(['comparison','and','or','not'])
function isValidPredicate(p: unknown): boolean {
  return !!p && typeof p === 'object' && PREDICATE_TYPES.has((p as any).type)
}

Type guard

function isPredicate(p: unknown): p is Predicate {
  return (
    !!p && typeof p === 'object' &&
    ['comparison','and','or','not'].includes((p as { type?: string }).type ?? '')
  )
}

Try / catch

catch (e) { if (e instanceof Error && e.message === 'Unsupported predicate') { console.error('Malformed predicate', predicate); throw e } throw e }

Prevention

When it happens

Trigger: Calling query builder APIs (where, having, join conditions) with a predicate whose `type` field is missing, misspelled, or a newly added variant the installed compiler version doesn't handle; also passing raw objects like `{ column: 'x', equals: 1 }` instead of builder-produced predicates, or a mismatched package version between data-table core and the MySQL adapter.

Common situations: Hand-writing predicate objects instead of using the builder; upgrading one data-table package but not the MySQL adapter so a new predicate kind is passed through; serializing/deserializing predicates (e.g. over IPC or JSON) and losing or corrupting the discriminant `type` field.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/649ee32a88d54705. Report an issue: GitHub.