{"record":{"id":"7d4245f832936c5c","repo":"dotnet/wpf","slug":"sr-clustermapfirstentrymustbezero","errorCode":null,"errorMessage":"SR.ClusterMapFirstEntryMustBeZero","messagePattern":"SR\\.ClusterMapFirstEntryMustBeZero","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphRun.cs","lineNumber":393,"sourceCode":"                                {\n                                    ushort current = clusterMap[i];\n                                    if ((current >= previous) && (current < glyphCount))\n                                    {\n                                        previous = current;\n                                    }\n                                    else\n                                    {\n                                        if (clusterMap[i] < clusterMap[i - 1])\n                                            throw new ArgumentException(SR.ClusterMapEntriesShouldNotDecrease, nameof(clusterMap));\n\n                                        if (clusterMap[i] >= GlyphCount)\n                                            throw new ArgumentException(SR.ClusterMapEntryShouldPointWithinGlyphIndices, nameof(clusterMap));\n                                    }\n                                }\n                            }\n                            else\n                            {\n                                throw new ArgumentException(SR.ClusterMapFirstEntryMustBeZero, nameof(clusterMap));\n                            }\n                        }\n                        else\n                        {\n                            throw new ArgumentException(SR.Format(SR.CollectionNumberOfElementsShouldBeEqualTo, characters.Count), nameof(clusterMap));\n                        }\n                    }\n                    else\n                    {\n                        if (GlyphCount != characters.Count)\n                            throw new ArgumentException(SR.Format(SR.CollectionNumberOfElementsShouldBeEqualTo, GlyphCount), nameof(clusterMap));\n                    }\n                }\n\n                if (caretStops != null && caretStops.Count != 0)\n                {\n                    if (caretStops.Count != CodepointCount + 1)\n                        throw new ArgumentException(SR.Format(SR.CollectionNumberOfElementsShouldBeEqualTo, CodepointCount + 1), nameof(caretStops));","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphRun.cs#L375-L411","documentation":"When a clusterMap is supplied to GlyphRun.Initialize, its first entry must be 0, indicating the first character maps to the first glyph. Any other first value leaves leading characters unmapped, so the run is rejected with ArgumentException on the clusterMap parameter.","triggerScenarios":"Calling the GlyphRun constructor, TryCreate, or EndInit with a clusterMap whose element 0 is non-zero, e.g. slicing a map from a larger run starting mid-cluster.","commonSituations":"Extracting a sub-run from shaped text and reusing the tail of the original clusterMap; off-by-one indexing when the shaper emits 1-based-looking values.","solutions":["Ensure clusterMap[0] == 0 (rebase entries by subtracting the original start offset)","Regenerate the map for the exact character/glyph range of this run","Skip passing clusterMap (pass null) if cluster information is not needed"],"exampleFix":"// before (sub-run of map {0,0,2,3} starting at index 2)\nint[] clusterMap = { 2, 3 };\n// after\nint[] clusterMap = { 0, 1 }; // rebased to start at 0","handlingStrategy":"validation","validationCode":"if (clusterMap != null && clusterMap.Length > 0 && clusterMap[0] != 0)\n    clusterMap = RebaseToZero(clusterMap);","typeGuard":"static bool FirstEntryIsZero(int[] map) => map == null || map.Length == 0 || map[0] == 0;","tryCatchPattern":"try { var run = new GlyphRun(...); }\ncatch (ArgumentException ex) when (ex.ParamName == \"clusterMap\") { /* rebase offsets */ }","preventionTips":["Rebase sub-run maps by subtracting the original first entry","Regenerate maps when slicing runs","Skip clusterMap when cluster info is unneeded"],"tags":["wpf","glyphrun","argument-validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}