{"record":{"id":"8c00ed33537ae2fb","repo":"dotnet/maui","slug":"indexer-did-not-contain-closing-bracket","errorCode":null,"errorMessage":"Indexer did not contain closing bracket","messagePattern":"Indexer did not contain closing bracket","errorType":"exception","errorClass":"FormatException","httpStatus":null,"severity":"error","filePath":"src/Controls/src/Core/BindingExpression.cs","lineNumber":244,"sourceCode":"\n\t\t\t\tp = p.Substring(1);\n\t\t\t}\n\n\t\t\tstring[] pathParts = p.Split(ExpressionSplit);\n\t\t\tfor (var i = 0; i < pathParts.Length; i++)\n\t\t\t{\n\t\t\t\tstring part = pathParts[i].Trim();\n\t\t\t\tif (part == string.Empty)\n\t\t\t\t\tthrow new FormatException(\"Path contains an empty part\");\n\n\t\t\t\tBindingExpressionPart indexer = null;\n\n\t\t\t\tint lbIndex = part.IndexOf(\"[\", StringComparison.Ordinal);\n\t\t\t\tif (lbIndex != -1)\n\t\t\t\t{\n\t\t\t\t\tint rbIndex = part.Length - 1;\n\t\t\t\t\tif (part[rbIndex] != ']')\n\t\t\t\t\t\tthrow new FormatException(\"Indexer did not contain closing bracket\");\n\n\t\t\t\t\tint argLength = rbIndex - lbIndex - 1;\n\t\t\t\t\tif (argLength == 0)\n\t\t\t\t\t\tthrow new FormatException(\"Indexer did not contain arguments\");\n\n\t\t\t\t\tstring argString = part.Substring(lbIndex + 1, argLength);\n\t\t\t\t\tindexer = new BindingExpressionPart(this, argString, true);\n\n\t\t\t\t\tpart = part.Substring(0, lbIndex);\n\t\t\t\t\tpart = part.Trim();\n\t\t\t\t}\n\t\t\t\tif (part.Length > 0)\n\t\t\t\t{\n\t\t\t\t\tvar next = new BindingExpressionPart(this, part);\n\t\t\t\t\tlast.NextPart = next;\n\t\t\t\t\t_parts.Add(next);\n\t\t\t\t\tlast = next;\n\t\t\t\t}","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/dotnet/maui/blob/f377ff1c5ee04d334d8a925f50c83a6b7afddf03/src/Controls/src/Core/BindingExpression.cs#L226-L262","documentation":"Thrown while parsing an indexer segment of a binding path when the part contains '[' but the final character is not ']'. The parser assumes an indexer occupies the end of the part and requires a matching closing bracket, e.g. Items[0] but not Items[0.","triggerScenarios":"Paths like \"Items[0\", \"List[abc\", or \"Dict[key\" — any indexer where the closing bracket is missing. Paths built by string concatenation that drop the closing bracket.","commonSituations":"Programmatic path construction with interpolated indices that omit ']'. Truncation of paths from external sources. Typo in XAML binding paths.","solutions":["Ensure every '[' in a path segment is paired with a trailing ']'.","Validate indexer segments so each '[' is immediately followed by a non-empty argument and a trailing ']' before binding.","Build indexer paths with a helper that always appends the closing bracket."],"exampleFix":"// before\nvar path = $\"Items[{index}\"; // missing ]\n\n// after\nvar path = $\"Items[{index}]\";","handlingStrategy":"validation","validationCode":"using System.Text.RegularExpressions;\nstatic bool HasBalancedIndexers(string path) =>\n    !Regex.IsMatch(path, @\"\\[[^\\]]*$\"); // no unclosed '[' at end of a segment\nif (!HasBalancedIndexers(path)) throw new ArgumentException(\"Malformed indexer\");","typeGuard":"static bool IsValidIndexerSegment(string seg) =>\n    !seg.Contains('[') || seg.TrimEnd().EndsWith(\"]\");","tryCatchPattern":null,"preventionTips":["Always close '[' with a trailing ']' when building indexer paths.","Validate path segments with a regex before binding.","Avoid manual string concatenation for indexers; use a helper."],"tags":["maui","binding","path","indexer","validation"],"backgroundTag":null,"analyzedSha":"f377ff1c5ee04d334d8a925f50c83a6b7afddf03","analyzedAt":"2026-08-13T14:26:18.069Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}