dotnet/wpf · error · FileFormatException

FileFormatException

Error message

FileFormatException

What it means

GlyphTypeface.Initialize throws System.IO.FileFormatException when DirectWrite fails to create a font face from the given URI source (fontFaceDWrite == null). This mirrors WPF 3.x behavior: passing an unsupported file — e.g. a composite font file (.compositeFont) or a path that is not a real TrueType/OpenType font — produces this exception. It means the file exists and was opened, but its contents are not a usable font face.

Solutions

  1. Verify the URI points to a genuine TrueType/OpenType (.ttf/.otf/.ttc) binary font, not a composite font definition file
  2. Open the file bytes and check for valid font signatures (0x00010000, 'OTTO', 'ttcf', 'true') before constructing GlyphTypeface
  3. Re-copy the font from a known-good source — the file may be truncated or corrupted
  4. Use a Pack URI that actually embeds the font resource in the assembly (Build Action: Resource) and confirm the resource exists
  5. Catch FileFormatException around GlyphTypeface construction and fall back to a bundled, verified font

Example fix

// before
glyphTypeface = new GlyphTypeface(new Uri("pack://application:,,,/Fonts/MyFont.compositeFont"));
// after
glyphTypeface = new GlyphTypeface(new Uri("pack://application:,,,/Fonts/MyFont.ttf"));
Defensive patterns

Strategy: validation

Validate before calling

bool IsValidFontFile(Uri fontUri)
{
    byte[] sig = new byte[4];
    using (var s = File.OpenRead(fontUri.LocalPath))
    {
        if (s.Read(sig, 0, 4) < 4) return false;
    }
    return sig[0] == 0x00 && sig[1] == 0x01 && sig[2] == 0x00 && sig[3] == 0x00
        || Encoding.ASCII.GetString(sig) is "OTTO" or "ttcf" or "true";
}

Try / catch

try { glyphTypeface = new GlyphTypeface(fontUri); }
catch (System.IO.FileFormatException ex)
{
    log.Warn($"Font file {fontUri} is not a usable font face", ex);
    glyphTypeface = new GlyphTypeface(fallbackFontUri);
}

Prevention

When it happens

Trigger: Calling new GlyphTypeface(uri) or ISupportInitialize EndInit with a URI pointing to a composite font file, a corrupted/truncated font file, a non-font file with a font extension, or a font format DirectWrite cannot parse.

Common situations: Deploying an app where the font file got corrupted or replaced during build/packaging; pointing GlyphTypeface at a .compositeFont definition (which is a WPF-level reference list, not a binary font); shipping a placeholder or zero-byte file; passing a resource path that resolves to an HTML error page or manifest instead of a font.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/b4198346547b5d3b. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/GlyphTypeface.cs:145

                && styleSimulations != StyleSimulations.ItalicSimulation 
                && styleSimulations != StyleSimulations.BoldSimulation
                && styleSimulations != StyleSimulations.BoldItalicSimulation)
            {
                throw new InvalidEnumArgumentException("styleSimulations", (int)styleSimulations, typeof(StyleSimulations));
            }

            _styleSimulations = styleSimulations;

            MS.Internal.Text.TextInterface.FontCollection fontCollection = DWriteFactory.GetFontCollectionFromFile(fontSourceUri);
            using (MS.Internal.Text.TextInterface.FontFace fontFaceDWrite = DWriteFactory.Instance.CreateFontFace(fontSourceUri,
                                                                                                                  (uint)faceIndex,
                                                                                                                  (MS.Internal.Text.TextInterface.FontSimulations)styleSimulations))
            {
                // This is the same behavior as 3.*. If we pass, for example, a path to a composite font file then a 
                // FileFormatException will be thrown!
                if (fontFaceDWrite == null)
                {
                    throw new System.IO.FileFormatException(typefaceSource);             
                }
                _font = fontCollection.GetFontFromFontFace(fontFaceDWrite);
            }

            _fontFace = new FontFaceLayoutInfo(_font);

            _fontSource = new FontSource(fontSourceUri);


            _initializationState = InitializationState.IsInitialized; // fully initialized
        }        

        #endregion Constructors

        //------------------------------------------------------
        //
        //  Public Methods
        //

View on GitHub (pinned to 81131a70a4)