{"record":{"id":"6d0d3914c9b8b058","repo":"AvaloniaUI/Avalonia","slug":"invalid-indexer-in-binding-expression-node-nodet","errorCode":null,"errorMessage":"Invalid indexer in binding expression: {node.NodeType}.","messagePattern":"Invalid indexer in binding expression: (.+?)\\.","errorType":"validation","errorClass":"ExpressionParseException","httpStatus":null,"severity":"error","filePath":"src/Avalonia.Base/Data/Core/Parsers/BindingExpressionVisitor.cs","lineNumber":108,"sourceCode":"                info,\n                (weakRef, propInfo) => CreateIndexerPropertyAccessor(weakRef, propInfo, index)));\n        }\n        else if (node.Indexer?.GetMethod is not null)\n        {\n            var getMethod = node.Indexer.GetMethod;\n            var setMethod = node.Indexer?.SetMethod;\n            var indexes = node.Arguments.Select(GetValue<object>).ToArray();\n            var info = new ClrPropertyInfo(\n                CommonPropertyNames.IndexerName,\n                x => getMethod.Invoke(x, indexes),\n                setMethod is not null ? (o, v) => setMethod.Invoke(o, indexes.Append(v).ToArray()) : null,\n                getMethod.ReturnType);\n            return Add(node.Object, node, x => x.Property(\n                info,\n                CreateInpcPropertyAccessor));\n        }\n\n        throw new ExpressionParseException(0, $\"Invalid indexer in binding expression: {node.NodeType}.\");\n    }\n\n    protected override Expression VisitMember(MemberExpression node)\n    {\n        return node.Member.MemberType switch\n        {\n            MemberTypes.Property => AddPropertyNode(node),\n            _ => throw new ExpressionParseException(0, $\"Invalid expression type in binding expression: {node.NodeType}.\"),\n        };\n    }\n\n    protected override Expression VisitMethodCall(MethodCallExpression node)\n    {\n        var method = node.Method;\n\n        if (method.Name == IndexerGetterName && node.Object is not null)\n        {\n            var property = TryGetPropertyFromMethod(method);","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/AvaloniaUI/Avalonia/blob/11c542726898ae954a1ef668c65ec79ec92ab17d/src/Avalonia.Base/Data/Core/Parsers/BindingExpressionVisitor.cs#L90-L126","documentation":"Thrown by BindingExpressionVisitor.VisitIndex when an IndexExpression does not match any of the four supported indexer patterns: (1) AvaloniaObject indexer with an AvaloniaProperty argument, (2) array element access, (3) single-integer-argument indexer with a public getter, or (4) general indexer with a public getter and arbitrary argument types. An indexer that has no GetMethod (write-only) or one whose object and indexer metadata do not satisfy any pattern falls through to this error.","triggerScenarios":"Accessing a write-only indexer (one with a setter but no getter) in a compiled binding lambda; using an indexer on an object whose type metadata is unavailable in the binding context; an IndexExpression constructed manually where node.Indexer is null and node.Object is not an array.","commonSituations":"Binding to a custom collection whose indexer is write-only; binding to an indexer that takes a non-integer key type where the getter is not public; using a multi-dimensional array indexer that does not match the 'Get' method pattern checked in VisitMethodCall.","solutions":["Ensure the indexer you bind to has a public getter (get accessor).","If the type is a dictionary or custom collection, verify the indexer's GetMethod is public and accessible.","For multi-dimensional arrays, use the dedicated ArrayElement path — verify the expression compiles to a standard array index, not a method call."],"exampleFix":"// before: write-only indexer\npublic string this[string key] { set { ... } }\n// binding:\n<TextBlock Text=\"{CompiledBinding [myKey]}\" />\n\n// after: add a public getter\npublic string this[string key] { get => _dict[key]; set { ... } }","handlingStrategy":"type-guard","validationCode":"// Check that an indexer has a public getter before using it in a binding\nstatic bool IndexerHasPublicGetter(Type type, Type indexType)\n{\n    foreach (var prop in type.GetDefaultMembers().OfType<PropertyInfo>())\n    {\n        if (prop.GetIndexParameters().Length == 1\n            && prop.GetIndexParameters()[0].ParameterType == indexType)\n            return prop.GetMethod?.IsPublic == true;\n    }\n    return false;\n}","typeGuard":"static bool IsBindableIndexer(IndexExpression node)\n{\n    if (node.Object?.Type.IsArray == true) return true;\n    if (node.Indexer?.GetMethod?.IsPublic == true) return true;\n    return false;\n}","tryCatchPattern":"try\n{\n    var path = BindingExpressionVisitor<TViewModel>.BuildPath<TItem>(expr);\n}\ncatch (ExpressionParseException ex) when (ex.Message.Contains(\"Invalid indexer\"))\n{\n    logger.LogError($\"Indexer has no public getter or unsupported signature: {ex.Message}\");\n}","preventionTips":["Ensure all indexers used in bindings have public get accessors.","For dictionary bindings, verify the key type matches the indexer parameter type.","Prefer ObservableCollection<T> and integer indexing for list-style bindings."],"tags":["avalonia","binding","compiled-binding","expression-tree","indexer","visitor","unsupported-operation"],"backgroundTag":null,"analyzedSha":"11c542726898ae954a1ef668c65ec79ec92ab17d","analyzedAt":"2026-08-13T11:57:40.261Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}