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
- Build predicates with the library's own builder functions (e.g. eq/and/or helpers) instead of plain object literals
- Check the predicate's `type` field at runtime and log the offending object to find the malformed value
- Ensure all @remix-run/data-table* packages are on the same version (align versions in package.json and reinstall)
- 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
- Always build predicates with the library's builder helpers
- Keep all data-table package versions aligned
- Validate deserialized predicates before use
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
- Unsupported predicate
- Unsupported operation kind
- upsert requires at least one value
- Unsupported predicate
- Unknown transaction token: + token.id
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/649ee32a88d54705.
Report an issue: GitHub.