{"record":{"id":"82110cd359683eac","repo":"dotnet/wpf","slug":"sr-glyphindexoutofrange","errorCode":null,"errorMessage":"SR.GlyphIndexOutOfRange","messagePattern":"SR\\.GlyphIndexOutOfRange","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphTypeface.cs","lineNumber":1061,"sourceCode":"                out bsb,\n                out baseline\n            );\n            return ah;\n        }\n\n        private unsafe MS.Internal.Text.TextInterface.GlyphMetrics GlyphMetrics(ushort             glyphIndex,\n                                                                                double             emSize,\n                                                                                float              pixelsPerDip,\n                                                                                TextFormattingMode textFormattingMode,\n                                                                                bool               isSideways)\n        {\n            MS.Internal.Text.TextInterface.GlyphMetrics glyphMetrics;\n\n            MS.Internal.Text.TextInterface.FontFace fontFaceDWrite = _font.GetFontFace();\n            try\n            {\n                if (glyphIndex >= fontFaceDWrite.GlyphCount)\n                    throw new ArgumentOutOfRangeException(nameof(glyphIndex), SR.Format(SR.GlyphIndexOutOfRange, glyphIndex));\n\n                glyphMetrics = new MS.Internal.Text.TextInterface.GlyphMetrics();\n\n                if (textFormattingMode == TextFormattingMode.Ideal)\n                {\n                    // We can safely pass pointers to glyphIndex and glyphMetrics since both are value types and are allocated on the stack.\n                    fontFaceDWrite.GetDesignGlyphMetrics(&glyphIndex, 1, &glyphMetrics);\n                }\n                else\n                {\n                    // We can safely pass pointers to glyphIndex and glyphMetrics since both are value types and are allocated on the stack.\n                    fontFaceDWrite.GetDisplayGlyphMetrics(&glyphIndex, 1, &glyphMetrics, checked((float)emSize),\n                        textFormattingMode != TextFormattingMode.Display, isSideways, pixelsPerDip);\n                }\n            }\n            finally\n            {\n                fontFaceDWrite.Release();","sourceCodeStart":1043,"sourceCodeEnd":1079,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphTypeface.cs#L1043-L1079","documentation":"The GlyphMetrics helper throws ArgumentOutOfRangeException with SR.GlyphIndexOutOfRange when the supplied glyphIndex is greater than or equal to the font's GlyphCount as reported by DirectWrite. Glyph indices are font-specific and bounded by the font's glyph table size; querying metrics, sidebearings, or advance geometry for an out-of-bounds index would access undefined data.","triggerScenarios":"Calling glyphMetrics, GetLeftSidebearing, GetRightSidebearing, GetTopSidebearing, or GetBottomSidebearing with a glyphIndex that came from a different font, from an unvalidated CharacterToGlyphMap miss, or from hardcoded assumptions about glyph numbering.","commonSituations":"Reusing cached glyph indices after switching the GlyphTypeface/font family; mapping a character to a glyph in one font and using the index against another font; fonts loaded via font fallback where indices differ per face; corrupted CharacterToGlyphMap lookups returning sentinel values.","solutions":["Verify glyphIndex < GlyphTypeface... glyph count before calling; expose the count via the underlying FontFace GlyphCount and guard the call","Obtain glyph indices from the same GlyphTypeface instance via its CharacterToGlyphMap, never across different faces","Reset/recompute cached glyph indices whenever the font face changes","Catch ArgumentOutOfRangeException around metric queries and treat them as missing-glyph cases"],"exampleFix":"// before\nvar metrics = glyphTypeface.GlyphMetrics(glyphIndex, textFormattingMode, pixelsPerDip);\n// after\nif (glyphIndex < fontFaceGlyphCount)\n    var metrics = glyphTypeface.GlyphMetrics(glyphIndex, textFormattingMode, pixelsPerDip);\nelse\n    /* treat as missing glyph / use 0 index */;","handlingStrategy":"validation","validationCode":"bool IsValidGlyphIndex(GlyphTypeface face, ushort glyphIndex)\n{\n    // DirectWrite bounds: must be < GlyphCount of the underlying font face\n    return glyphIndex < face.CharToFriendlyGlyphNameMap.Count; // or cache face's GlyphCount via _font.GetFontFace().GlyphCount\n}","typeGuard":"static bool IsInGlyphRange(ushort glyphIndex, ushort glyphCount) => glyphIndex < glyphCount;","tryCatchPattern":"try\n{\n    var metrics = glyphTypeface.GlyphMetrics(glyphIndex, mode, pixelsPerDip);\n}\ncatch (ArgumentOutOfRangeException ex) when (ex.ParamName == \"glyphIndex\")\n{\n    // treat as missing glyph: fall back to index 0 (.notdef)\n    var metrics = glyphTypeface.GlyphMetrics(0, mode, pixelsPerDip);\n}","preventionTips":["Only reuse glyph indices with the same GlyphTypeface they were derived from","Clear caches of glyph indices when the font face/family changes","Fall back to glyph index 0 (.notdef) for unmapped or invalid indices","Validate CharacterToGlyphMap lookups for sentinel/miss values before querying metrics"],"tags":["wpf","fonts","argumentoutofrangeexception","glyph-index"],"backgroundTag":"argument-out-of-range","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}