dotnet/wpf · error · FileFormatException

SR.InvalidStringFormat

Error message

SR.InvalidStringFormat

What it means

FileFormatException thrown by ReadLengthPrefixedString when reader.ReadBytes(length) returns fewer bytes than the declared length prefix — the stream ended prematurely. It signals a truncated string payload inside a publish/use-license stream.

Solutions

  1. Verify the stream is fully intact (compare against expected size/checksum) before parsing
  2. Re-acquire or regenerate the license data instead of parsing the damaged stream
  3. Restore the compound file from backup
  4. Check that the stream is not being consumed concurrently by another reader that advanced its position

Example fix

// before: assuming a complete stream
var license = LoadPublishLicense(packStream); // throws if truncated
// after: check completeness first
if (!packStream.CanRead || packStream.Length == 0)
    throw new InvalidDataException("License stream is empty or unreadable.");
using (var buffered = new MemoryStream(ReadAllBytes(packStream)))
{
    var license = LoadPublishLicense(buffered);
}
Defensive patterns

Strategy: validation

Validate before calling

bool StringFitsInStream(Stream s)
{
    if (s.Length - s.Position < sizeof(Int32)) return false;
    long pos = s.Position;
    using (var br = new BinaryReader(s, Encoding.UTF8, leaveOpen: true))
    {
        int len = br.ReadInt32();
        bool ok = len >= 0 && s.Position + len <= s.Length;
        s.Position = pos;
        return ok;
    }
}

Try / catch

try
{
    var license = LoadPublishLicense(stream);
}
catch (FileFormatException ex)
{
    logger.LogError(ex, "License stream truncated: declared string length exceeds remaining bytes.");
    throw new InvalidDataException("Truncated license stream; re-acquire the license.", ex);
}

Prevention

When it happens

Trigger: Any call path through ReadLengthPrefixedString (LoadPublishLicense, LoadUserFromStream's base64UserName, LoadUseLicenseAndUserFromStream, LoadUseLicenseFromStream) where the length prefix promises N bytes but fewer than N remain in the stream.

Common situations: Truncated downloads or file copies; compound files damaged by disk errors; streams written by a buggy writer that under-counted the string length; reading a stream already positioned at/past its end.

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/6928ee7d1d2d2a54. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/IO/Packaging/CompoundFile/RightsManagementEncryptionTransform.cs:1183

        /// file with a huge length prefix from making us allocate all our memory.
        /// </param>
        private static string
        ReadLengthPrefixedString(
            BinaryReader reader,
            Encoding encoding,
            int maxLength
            )
        {
            Int32 length = reader.ReadInt32();
            if (length > maxLength)
            {
                throw new FileFormatException(SR.Format(SR.ExcessiveLengthPrefix, length, maxLength));
            }

            byte[] bytes = reader.ReadBytes(length);
            if (bytes.Length != length)
            {
                throw new FileFormatException(SR.InvalidStringFormat);
            }

            string s = encoding.GetString(bytes);

            SkipDwordPadding(bytes.Length, reader);

            return s;
        }

        /// <summary>
        /// Skip past the DWORD padding bytes at the end of a string of the specified length.
        /// </summary>
        /// <param name="length">
        /// Length in bytes of the string that was read.
        /// </param>
        /// <param name="reader">
        /// Binary reader from which the string was read.
        /// </param>

View on GitHub (pinned to 81131a70a4)