{"record":{"id":"1221e5c4d21ba942","repo":"stride3d/stride","slug":"the-rendered-character-is-too-big-for-the-cache-texture","errorCode":null,"errorMessage":"The rendered character is too big for the cache texture","messagePattern":"The rendered character is too big for the cache texture","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Graphics/Font/FontCacheManager.cs","lineNumber":83,"sourceCode":"        {\n            if (character.Bitmap == null)\n                throw new ArgumentNullException(\"character\");\n\n            if (character.IsBitmapUploaded)\n                throw new InvalidOperationException($\"The character '{character.Character}' upload has been requested while its current glyph is valid.\");\n\n            var targetSize = new Int2(character.Bitmap.Width, character.Bitmap.Rows);\n            if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))\n            {\n                // not enough space to place the new character -> remove less used characters and try again\n                RemoveLessUsedCharacters();\n                if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))\n                {\n                    // memory is too fragmented in order to place the new character -> clear all the characters and restart.\n                    // TODO: This is invalid, we might delete character from current frame!\n                    ClearCache();\n                    if (!packer.Insert(targetSize.X, targetSize.Y, ref character.Glyph.Subrect))\n                        throw new InvalidOperationException(\"The rendered character is too big for the cache texture\");\n                }\n            }\n            // Upload the bitmap to the atlas texture, with a 1px transparent border extending\n            // beyond the allocated region to clear any stale pixels from previously freed glyphs.\n            // This overlaps into neighbors' transparent borders (which are also zeroed), so no\n            // glyph data is corrupted. Prevents bilinear filtering artifacts when scaling fonts.\n            if (character.Bitmap.Rows != 0 && character.Bitmap.Width != 0)\n            {\n                var texW = cacheTextures[0].ViewWidth;\n                var texH = cacheTextures[0].ViewHeight;\n\n                // Expand the upload region by 1px on each side, clamped to texture bounds\n                int left = Math.Max(0, character.Glyph.Subrect.Left - 1);\n                int top = Math.Max(0, character.Glyph.Subrect.Top - 1);\n                int right = Math.Min(texW, character.Glyph.Subrect.Right + 1);\n                int bottom = Math.Min(texH, character.Glyph.Subrect.Bottom + 1);\n                int expandedW = right - left;\n                int expandedH = bottom - top;","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Graphics/Font/FontCacheManager.cs#L65-L101","documentation":"The dynamic font atlas tries to insert the glyph rect via the packer; if it fails it evicts less-used characters, then clears the entire cache, and if insertion still fails, the glyph simply does not fit the fixed-size cache texture. It throws InvalidOperationException('The rendered character is too big for the cache texture') because no eviction strategy can help.","triggerScenarios":"Rendering a glyph whose pixel size (Width x Rows) exceeds the atlas texture dimensions — typically extremely large font sizes, huge scale factors, or a deliberately tiny cache texture size.","commonSituations":"A font rendered at very large point sizes (e.g. title text at 300pt+ on low-res virtual resolution); misconfigured font cache size; DPI/virtual-resolution scaling multiplying glyph size beyond the atlas.","solutions":["Increase the font atlas/cache texture size (render target settings for the font system)","Reduce the font size or scale factor used to render the offending character","Guard glyph size before upload: skip or pre-split characters whose bitmap exceeds atlas dimensions","Ensure virtual resolution/DPI scaling is not inflating the requested glyph size unexpectedly"],"exampleFix":"// before\nif (!packer.Insert(w, h, ref subrect)) { /* eventually throws */ }\n// after\nif (w > atlasSize.X || h > atlasSize.Y)\n{\n    log.Warning($\"Glyph {character} too large ({w}x{h}) for atlas; skipping.\");\n    return;\n}\npacker.Insert(w, h, ref subrect);","handlingStrategy":"validation","validationCode":"var size = new Int2(character.Bitmap.Width, character.Bitmap.Rows);\nif (size.X > atlasWidth || size.Y > atlasHeight)\n{\n    log.Warning($\"Glyph '{character.Character}' ({size.X}x{size.Y}) exceeds atlas; skipping.\");\n    return;\n}","typeGuard":"bool FitsInAtlas(CharacterSpecification c, Int2 atlas) =>\n    c?.Bitmap != null && c.Bitmap.Width <= atlas.X && c.Bitmap.Rows <= atlas.Y;","tryCatchPattern":"try { cache.UploadCharacterBitmap(commandList, character); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"too big for the cache texture\"))\n{\n    log.Error($\"Glyph '{character.Character}' exceeds atlas size. Increase cache size or reduce font scale.\");\n}","preventionTips":["Size the font cache texture for the largest font size you render","Clamp or cap font scaling before rendering to atlas","Pre-check glyph bitmap dimensions against atlas capacity in upload helpers"],"tags":["fonts","atlas","texture-size","capacity"],"backgroundTag":"value-out-of-range","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}