{"record":{"id":"25e4fc1cb11ca87d","repo":"stride3d/stride","slug":"failed-to-load-font-from-filepath-freetype-error-err","errorCode":null,"errorMessage":"Failed to load font from '{filePath}' (FreeType error {err})","messagePattern":"Failed to load font from '(.+?)' \\(FreeType error (.+?)\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Graphics/Font/FontManager.cs","lineNumber":162,"sourceCode":"        public void LoadFontFromFileSystem(string fontName, string filePath, FontStyle style)\n        {\n            var cacheKey = FontHelper.GetFontPath(fontName, style);\n\n            lock (freetypeLock)\n            {\n                if (cachedFontFaces.ContainsKey(cacheKey))\n                    return;\n\n                var fontData = File.ReadAllBytes(filePath);\n                var handle = GCHandle.Alloc(fontData, GCHandleType.Pinned);\n\n                fixed (byte* ptr = fontData)\n                {\n                    int err = FreeTypeNative.FT_New_Memory_Face(freetypeLibrary, ptr, new CLong(fontData.Length), new CLong(0), out FT_FaceRec* face);\n                    if (err != 0)\n                    {\n                        handle.Free();\n                        throw new InvalidOperationException($\"Failed to load font from '{filePath}' (FreeType error {err})\");\n                    }\n                    cachedFontFaces[cacheKey] = ((nint)face, handle);\n                }\n            }\n        }\n\n        private void GenerateCharacterGlyph(CharacterSpecification character, bool renderBitmap, bool computeMetrics)\n        {\n            // Reset and (re)compute Glyph.XAdvance only on the metric pass. The async builder thread\n            // re-renders the bitmap of an already-measured glyph and must leave XAdvance untouched:\n            // text measurement reads it lock-free while the bitmap is still pending, so zeroing it\n            // here — even transiently — makes the last glyph on a line measure as zero-width and the\n            // UI background fall short of the text.\n            if (computeMetrics)\n                ResetGlyph(character);\n\n            // let the glyph info null if the size is not valid\n            if (character.Size.X < 1 || character.Size.Y < 1)","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Graphics/Font/FontManager.cs#L144-L180","documentation":"LoadFontFromFileSystem reads the font file into memory and asks FreeType to parse it via FT_New_Memory_Face. A nonzero error means FreeType could not parse the data as a supported font format, so an InvalidOperationException is thrown with the file path and FreeType error code.","triggerScenarios":"Calling LoadFontFromFileSystem with a file that exists but is not a valid font (corrupted download, truncated file, wrong extension, unsupported format like a bitmap-only font).","commonSituations":"Deploying a placeholder/zero-byte .ttf; fonts corrupted by source-control line-ending mangling or incomplete copy; pointing at an HTML error page saved as .ttf; font format not compiled into the shipped FreeType build.","solutions":["Validate the file is a real TrueType/OpenType font (check magic bytes 0x00010000 / 'OTTO') before loading","Re-copy the font file from a known-good source; check file size > 0","Decode the FreeType error code in the message (e.g. 2 = cannot open resource, 3 = unknown file format) to target the fix","Ensure the deployment pipeline copies font files verbatim (no encoding/line-ending transforms)"],"exampleFix":"// before\nfontManager.LoadFontFromFileSystem(name, suspiciousPath, style);\n// after\nvar bytes = File.ReadAllBytes(suspiciousPath);\nif (bytes.Length < 12)\n    throw new InvalidDataException($\"Font file too small or corrupt: {suspiciousPath}\");\nfontManager.LoadFontFromFileSystem(name, suspiciousPath, style);","handlingStrategy":"validation","validationCode":"var data = File.ReadAllBytes(filePath);\nif (data.Length < 12) throw new InvalidDataException($\"Not a font file: {filePath}\");\nbool validMagic = data[0]==0 && data[1]==1 && data[2]==0 && data[3]==0\n               || data[0]==(byte)'O' && data[1]==(byte)'T' && data[2]==(byte)'T' && data[3]==(byte)'O';","typeGuard":null,"tryCatchPattern":"try { fontManager.LoadFontFromFileSystem(name, path, style); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"FreeType error\"))\n{\n    log.Error($\"Font load failed for {path}; falling back to default font\", ex);\n    LoadDefaultFont();\n}","preventionTips":["Verify font files load in a tool (e.g. fontconfig) before shipping","Ship fonts as binary content; disable any transform that could corrupt them","Log and map FreeType error codes for faster diagnosis"],"tags":["fonts","freetype","file-loading"],"backgroundTag":"file-read-failed","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}