dotnet/wpf · error · InvalidOperationException

SR.DocumentStreamMustBeFileSource

Error message

SR.DocumentStreamMustBeFileSource

What it means

SwapWithOriginal throws InvalidOperationException with SR.DocumentStreamMustBeFileSource when the original DocumentStream has no _xpsFileToken, i.e. the original was not created from an XPS file on disk. Swapping a temporary stream back requires both sides to be file-backed.

Solutions

  1. Create the original DocumentStream from a file path (file URI) so it has an XPS file token before using swap logic.
  2. For stream-sourced documents, persist to a temporary file first, then perform file-based operations.
  3. Skip swap/commit operations for non-file-backed documents and handle them via an alternate save path.

Example fix

// before
var doc = XpsDocument(... from MemoryStream ...); // later SwapWithOriginal fails
// after
write stream to temp .xps file; open DocumentStream from the file path, then swap
Defensive patterns

Strategy: validation

Validate before calling

bool originalIsFileBacked = docStream.Original != null && docStream.Original.Location != null && docStream.Original.Location.IsFile;

Try / catch

try { docStream.SwapWithOriginal(); }
catch (InvalidOperationException) { /* persist stream to temp file, retry */ }

Prevention

When it happens

Trigger: SwapWithOriginal() called where the temporary stream is valid but its _original was created from a memory stream or non-file source (_original._xpsFileToken == null).

Common situations: Opening an XPS package from a stream (e.g. downloaded or in-memory XPS) and then attempting internal save/commit flows that assume a file-backed original.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationUI/MS/Internal/Documents/Application/DocumentStream.cs:508

    /// to logically allow in place editing for the user.
    /// 
    /// After use this object is unusable and should be disposed as the
    /// temporary file is gone; it has become the original. In the event of an
    /// error while swapping the file, the file no longer becomes the original,
    /// but this object still becomes unusable.
    /// </remarks>
    internal bool SwapWithOriginal()
    {
        bool success = false;

        if (_original == null)
        {
            throw new InvalidOperationException(
                SR.DocumentStreamMustBeTemporary);
        }
        if (_original._xpsFileToken == null)
        {
            throw new InvalidOperationException(
                SR.DocumentStreamMustBeFileSource);
        }
        if (_xpsFileToken == null)
        {
            throw new InvalidOperationException(
                SR.DocumentStreamMustBeFileSource);
        }

        Trace.SafeWrite(
            Trace.File,
            "Begining file swap between {0} and {1}.",
            _xpsFileToken.Location,
            _original._xpsFileToken.Location);

        ThrowIfInvalidXpsFileForSave(_xpsFileToken.Location);
        ThrowIfInvalidXpsFileForOpen(_original._xpsFileToken.Location);

        string original = _original._xpsFileToken.Location.LocalPath;

View on GitHub (pinned to 81131a70a4)