dotnet/wpf · error · FileFormatException

FileFormatException(SourceUri, e)

Error message

FileFormatException(SourceUri, e)

What it means

TrueTypeFontDriver's constructor reads the font file's offset table; CheckedPointer bounds-checks every access and throws ArgumentOutOfRangeException when a table offset/size points outside the file. The driver catches it and rethrows FileFormatException(SourceUri, e), converting 'bad pointer' into 'this font file is malformed or truncated'.

Solutions

  1. Re-install or re-download the font file and verify its size/checksum
  2. Catch FileFormatException around font loading and fall back to a fallback font family
  3. Check InnerException for the CheckedPointer offset that ran out of range
  4. Validate the file is a real TrueType font (starts with 0x00010000 or 'true') before loading

Example fix

// before
driver = new TrueTypeFontDriver(stream, uri); // throws on truncated font
// after
try { driver = new TrueTypeFontDriver(stream, uri); }
catch (FileFormatException e) {
    log.Warn($"Malformed font {uri}: {e.Message}");
    driver = null; // fall back
}
Defensive patterns

Strategy: try-catch

Validate before calling

using var fs = File.OpenRead(path);
if (fs.Length < 12) throw new IOException("Not a TrueType font: too small");
Span<byte> hdr = stackalloc byte[4]; fs.ReadExactly(hdr);
bool plausible = hdr[0]==0 && hdr[1]==1 && hdr[2]==0 && hdr[3]==0; // 0x00010000

Type guard

bool LooksLikeTrueType(byte[] b) => b.Length >= 4 && (b[0]==0 && b[1]==1 && b[2]==0 && b[3]==0 || b[0]==(byte)'t' && b[1]==(byte)'r' && b[2]==(byte)'u' && b[3]==(byte)'e');

Try / catch

try { LoadFont(stream); }
catch (FileFormatException e)
{
    log.Warn($"Font {e.SourceUri} is malformed: {e.InnerException?.Message}");
    UseFallbackFont();
}

Prevention

When it happens

Trigger: Constructing a TrueTypeFontDriver (e.g. via ComputeTypefaceFontDriver / font enumeration) on a font stream whose header claims offsets or table lengths beyond the actual stream length.

Common situations: Corrupted font file from an interrupted download, font embedded in a resource that was truncated, disk-full during font deployment, running the parser on a non-font file renamed to .ttf.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/MS/internal/FontFace/FontDriver.cs:144

                    _technology = FontTechnology.TrueTypeCollection;
                    seekPosition += 4; // skip version
                    _numFaces = ReadOpenTypeLong(seekPosition);
                }
                else if (typeTag == TrueTypeTags.OTTO)
                {
                    _technology = FontTechnology.PostscriptOpenType;
                    _numFaces = 1;
                }
                else
                {
                    _technology = FontTechnology.TrueType;
                    _numFaces = 1;
                }
            }
            catch (ArgumentOutOfRangeException e)
            {
                // convert exceptions from CheckedPointer to FileFormatException
                throw new FileFormatException(SourceUri, e);
            }
        }

        internal void SetFace(int faceIndex)
        {
            if (_technology == FontTechnology.TrueTypeCollection)
            {
                ArgumentOutOfRangeException.ThrowIfNegative(faceIndex);
                ArgumentOutOfRangeException.ThrowIfGreaterThanOrEqual(faceIndex, _numFaces);
            }
            else
            {
                if (faceIndex != 0)
                    throw new ArgumentOutOfRangeException(nameof(faceIndex), SR.FaceIndexValidOnlyForTTC);
            }

            try
            {

View on GitHub (pinned to 81131a70a4)