{"record":{"id":"5380b31455d11e6d","repo":"clockworklabs/SpacetimeDB","slug":"unsupported-predicate-type-value-gettype-name","errorCode":null,"errorMessage":"Unsupported predicate type '{value.GetType().Name}'. Expected BoolExpr<{typeof(TRow).Name}> or a boolean column.","messagePattern":"Unsupported predicate type '(.+?)'\\. Expected BoolExpr<(.+?)> or a boolean column\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs","lineNumber":97,"sourceCode":"    public override string ToString() => Sql;\n\n    public static implicit operator BoolExpr<TRow>(bool value) => new(value ? \"TRUE\" : \"FALSE\");\n\n    public static implicit operator BoolExpr<TRow>(Col<TRow, bool> col) => col.Eq(true);\n\n    public static implicit operator BoolExpr<TRow>(IxCol<TRow, bool> col) => col.Eq(true);\n}\n\ninternal static class QueryPredicate\n{\n    internal static BoolExpr<TRow> ToBoolExpr<TRow>(object value) =>\n        value switch\n        {\n            BoolExpr<TRow> expr => expr,\n            Col<TRow, bool> col => col.Eq(true),\n            IxCol<TRow, bool> col => col.Eq(true),\n            bool b => new BoolExpr<TRow>(b ? \"TRUE\" : \"FALSE\"),\n            _ => throw new ArgumentException(\n                $\"Unsupported predicate type '{value.GetType().Name}'. Expected BoolExpr<{typeof(TRow).Name}> or a boolean column.\",\n                nameof(value)\n            ),\n        };\n}\n\npublic readonly struct IxJoinEq<TLeftRow, TRightRow>\n{\n    internal string LeftRefSql { get; }\n    internal string RightRefSql { get; }\n\n    internal IxJoinEq(string leftRefSql, string rightRefSql)\n    {\n        LeftRefSql = leftRefSql;\n        RightRefSql = rightRefSql;\n    }\n}\n","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/bindings-csharp/BSATN.Runtime/QueryBuilder.cs#L79-L115","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nvar q = table.Filter(t => t.Count); // int column, throws 'Unsupported predicate type'\n\n// after\nvar q = table.Filter(t => t.Count > 0); // BoolExpr<TRow> via operator","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"static bool IsSupportedPredicate<TRow>(object? predicate) =>\n    predicate is BoolExpr<TRow> or Col<TRow, bool> or IxCol<TRow, bool> or bool;","tryCatchPattern":"try { query = table.Filter(pred); }\ncatch (ArgumentException ex) when (ex.Message.StartsWith(\"Unsupported predicate type\"))\n{ /* rewrite the predicate with column operators before retrying */ }","preventionTips":["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"],"tags":["csharp","query-builder","predicate","sql","spacetimedb"],"backgroundTag":"query-predicate-type-mismatch","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}