{"record":{"id":"4837e337788a374d","repo":"AvaloniaUI/Avalonia","slug":"catch-blocks-are-not-allowed-in-binding-expression","errorCode":null,"errorMessage":"Catch blocks are not allowed in binding expressions.","messagePattern":"Catch blocks are not allowed in binding expressions\\.","errorType":"validation","errorClass":"ExpressionParseException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Data/Core/Parsers/BindingExpressionVisitor.cs","lineNumber":205,"sourceCode":"                return Add(node.Operand, node, x => x.TypeCast(node.Type));\n            }\n        }\n        else if (node.NodeType == ExpressionType.TypeAs)\n        {\n            return Add(node.Operand, node, x => x.TypeCast(node.Type));\n        }\n\n        throw new ExpressionParseException(0, $\"Invalid expression type in binding expression: {node.NodeType}.\");\n    }\n\n    protected override Expression VisitBlock(BlockExpression node)\n    {\n        throw new ExpressionParseException(0, $\"Invalid expression type in binding expression: {node.NodeType}.\");\n    }\n\n    protected override CatchBlock VisitCatchBlock(CatchBlock node)\n    {\n        throw new ExpressionParseException(0, \"Catch blocks are not allowed in binding expressions.\");\n    }\n\n    protected override Expression VisitConditional(ConditionalExpression node)\n    {\n        throw new ExpressionParseException(0, $\"Invalid expression type in binding expression: {node.NodeType}.\");\n    }\n\n    protected override Expression VisitDynamic(DynamicExpression node)\n    {\n        throw new ExpressionParseException(0, \"Dynamic expressions are not allowed in binding expressions.\");\n    }\n\n    protected override ElementInit VisitElementInit(ElementInit node)\n    {\n        throw new ExpressionParseException(0, \"Element init expressions are not valid in a binding expression.\");\n    }\n\n    protected override Expression VisitGoto(GotoExpression node)","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Data/Core/Parsers/BindingExpressionVisitor.cs#L187-L223","documentation":"Thrown unconditionally by BindingExpressionVisitor.VisitCatchBlock whenever a CatchBlock node appears in the expression tree. Catch blocks are produced by try-catch expressions in statement lambdas. Since compiled bindings represent a declarative property path, exception handling constructs are never valid.","triggerScenarios":"Using a try-catch inside a statement lambda in a compiled binding: x => { try { return x.Risky; } catch { return null; } } produces a TryExpression containing CatchBlock nodes that trigger this error when visited.","commonSituations":"Attempting to handle null-reference or conversion exceptions inline within the binding expression; wrapping risky property access in try-catch instead of using the binding's FallbackValue or null-conditional operator; migrating error-handling code-behind into a binding lambda.","solutions":["Use the binding's FallbackValue or TargetNullValue to handle null or error results instead of try-catch.","Use the null-conditional operator (x?.Y) in the lambda for null-safe property access.","Move any exception-handling logic into a view-model property and bind to that property."],"exampleFix":"// before: try-catch in compiled binding\nCompiledBinding(x => { try { return x.MightBeNull.Name; } catch { return \"\"; } })\n\n// after: null-conditional + FallbackValue\n<TextBlock Text=\"{CompiledBinding MightBeNull?.Name, FallbackValue=N/A}\" />","handlingStrategy":"validation","validationCode":"// Detect try-catch usage in a binding lambda at design time\nstatic bool HasTryCatch<TIn, TOut>(Expression<Func<TIn, TOut>> expr)\n{\n    bool found = false;\n    expr.Body.Visit(b =>\n    {\n        if (b is TryExpression) found = true;\n    });\n    return found;\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    var path = BindingExpressionVisitor<TViewModel>.BuildPath<TProp>(expr);\n}\ncatch (ExpressionParseException ex) when (ex.Message.Contains(\"Catch blocks\"))\n{\n    logger.LogError(\"Try-catch is not allowed in compiled binding expressions. Use FallbackValue or null-conditional access.\");\n}","preventionTips":["Never use try-catch in a compiled binding lambda.","Use the binding's FallbackValue for error recovery.","Use null-conditional access (x?.Y) for null safety instead of try-catch."],"tags":["avalonia","binding","compiled-binding","expression-tree","catch-block","visitor","unsupported-operation"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}