clockworklabs/SpacetimeDB · error · ArgumentException
Unsupported predicate type '{value.GetType().Name}'. Expecte
Error message
Unsupported predicate type '{value.GetType().Name}'. Expected BoolExpr<{typeof(TRow).Name}> or a boolean column. What it means
The query builder normalizes every predicate through QueryPredicate.ToBoolExpr, which accepts exactly four shapes: BoolExpr<TRow>, a bool column (Col<TRow,bool> or IxCol<TRow,bool>), and a plain bool. Anything else - an int column, a lambda, a string, or a predicate built for a different table's row type - cannot become a SQL WHERE clause and is rejected with ArgumentException.
Source
Thrown at crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs:97
public override string ToString() => Sql;
public static implicit operator BoolExpr<TRow>(bool value) => new(value ? "TRUE" : "FALSE");
public static implicit operator BoolExpr<TRow>(Col<TRow, bool> col) => col.Eq(true);
public static implicit operator BoolExpr<TRow>(IxCol<TRow, bool> col) => col.Eq(true);
}
internal static class QueryPredicate
{
internal static BoolExpr<TRow> ToBoolExpr<TRow>(object value) =>
value switch
{
BoolExpr<TRow> expr => expr,
Col<TRow, bool> col => col.Eq(true),
IxCol<TRow, bool> col => col.Eq(true),
bool b => new BoolExpr<TRow>(b ? "TRUE" : "FALSE"),
_ => throw new ArgumentException(
$"Unsupported predicate type '{value.GetType().Name}'. Expected BoolExpr<{typeof(TRow).Name}> or a boolean column.",
nameof(value)
),
};
}
public readonly struct IxJoinEq<TLeftRow, TRightRow>
{
internal string LeftRefSql { get; }
internal string RightRefSql { get; }
internal IxJoinEq(string leftRefSql, string rightRefSql)
{
LeftRefSql = leftRefSql;
RightRefSql = rightRefSql;
}
}
View on GitHub (pinned to 524b4487d9)
Solutions
- Build explicit boolean expressions with the column operators, e.g. t.Count > 0 or t.Status.Eq("active"), which yield BoolExpr<TRow>
- For bool columns, pass the column directly or write t.Flag.Eq(true); both are accepted
- Make sure the row type parameter matches the table being queried - do not mix predicates across tables
- Replace lambdas with the builder's And/Or/Not composition over columns
Example fix
// before var q = table.Filter(t => t.Count); // int column, throws 'Unsupported predicate type' // after var q = table.Filter(t => t.Count > 0); // BoolExpr<TRow> via operator
Defensive patterns
Strategy: type-guard
Type guard
static bool IsSupportedPredicate<TRow>(object? predicate) =>
predicate is BoolExpr<TRow> or Col<TRow, bool> or IxCol<TRow, bool> or bool; Try / catch
try { query = table.Filter(pred); }
catch (ArgumentException ex) when (ex.Message.StartsWith("Unsupported predicate type"))
{ /* rewrite the predicate with column operators before retrying */ } Prevention
- Always build predicates from column operators (col == value, col.Gt(n)) so they are BoolExpr<TRow>
- Never pass bare lambdas or non-bool columns to Filter/Where/And/Or
- Keep one helper per table type so row-type parameters cannot be mixed
When it happens
Trigger: Passing a raw non-bool column like table.Filter(t => t.Count) where Count is Col<TRow,int>; handing a lambda (boxed as Func<...>) instead of an expression built from column operators; reusing a BoolExpr<OtherRow> built against a different table in this table's query.
Common situations: Porting LINQ-style code and assuming lambdas compile to filters; copy-pasting predicates between queries on different entity types; treating truthiness of numeric columns like C-style languages.
Related errors
- Invalid hex character '{c}'.
- Cannot semijoin a table to itself
- Cannot extract table name from query
- Cannot extract accessor name from query
- never types are not yet supported in C# output
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/5380b31455d11e6d.
Report an issue: GitHub.