dotnet/wpf · error · FileFormatException

SR.VersionStreamMissing

Error message

SR.VersionStreamMissing

What it means

FileFormatException (SR.VersionStreamMissing) thrown by VersionedStreamOwner.ReadAttempt when the stream requires a version header but none was found (_fileVersion == null): either throwIfEmpty was requested on an empty stream, or the stream has data but no persisted FormatVersion. Versioned compound-file streams must start with a version block identifying reader/updater versions.

Solutions

  1. Ensure the stream was created through the versioned-stream writer so the FormatVersion header is persisted first
  2. Regenerate or restore the file — a missing header cannot be repaired by reading
  3. If an empty stream is legitimate, use the non-throwing path (throwIfEmpty=false) instead of the strict read entry point
  4. Detect the format before opening: check for the version signature and use a plain stream when absent

Example fix

// before: strict read on a possibly headerless/empty stream
int n = versionedStream.Read(buffer, 0, buffer.Length); // VersionStreamMissing
// after: probe for data before the strict read
if (versionedStream.Length == 0)
{
    return 0; // legitimately empty
}
int n = versionedStream.Read(buffer, 0, buffer.Length);
Defensive patterns

Strategy: validation

Validate before calling

static bool HasVersionHeader(Stream s)
{
    if (s.Length < MinVersionBlockSize) return false;
    long pos = s.Position;
    byte[] magic = new byte[VersionMagic.Length];
    int n = s.Read(magic, 0, magic.Length);
    s.Position = pos;
    return n == magic.Length && magic.AsSpan().SequenceEqual(VersionMagic);
}

Try / catch

try
{
    int n = versionedStream.Read(buffer, 0, buffer.Length);
}
catch (FileFormatException ex) when (ex.Message.Contains("version"))
{
    // no FormatVersion present: handle as legacy/plain data or reject
    HandleAsUnversionedData();
}

Prevention

When it happens

Trigger: Reading from a versioned stream that contains no FormatVersion header — e.g. the stream was created by non-versioned code, the header was overwritten/truncated, or Read/ReadByte was called with throwIfEmpty=true on a zero-length stream.

Common situations: Opening a plain (non-versioned) file through the versioned-stream path; files damaged at the header; a writer that crashed before persisting the version block; mixing legacy and versioned compound-file formats.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

        /// Callback for when a Stream is read from
        /// </summary>
        /// <remarks>Can modify the FormatVersion stream pointer.</remarks>
        /// <param name="throwIfEmpty">caller requires an existing FormatVersion</param>
        internal void ReadAttempt(bool throwIfEmpty)
        {
            CheckDisposed();    // central location

            // only do this once
            if (!_readOccurred)
            {
                // read
                EnsureParsed();

                // first usage?
                if (throwIfEmpty || BaseStream.Length > 0)
                {
                    if (_fileVersion == null)
                        throw new FileFormatException(SR.VersionStreamMissing);

                    // compare versions
                    // verify we can read this version
                    if (!_fileVersion.IsReadableBy(_codeVersion.ReaderVersion))
                    {
                        throw new FileFormatException(
                                        SR.Format(
                                            SR.ReaderVersionError,
                                            _fileVersion.ReaderVersion,
                                            _codeVersion
                                            )
                                        );
                    }
                }
                _readOccurred = true;
            }
        }

View on GitHub (pinned to 81131a70a4)