{"record":{"id":"d7b0f078ccb33fdd","repo":"dotnet/wpf","slug":"sr-documentstreammustbefilesource","errorCode":null,"errorMessage":"SR.DocumentStreamMustBeFileSource","messagePattern":"SR\\.DocumentStreamMustBeFileSource","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationUI/MS/Internal/Documents/Application/DocumentStream.cs","lineNumber":508,"sourceCode":"    /// to logically allow in place editing for the user.\n    /// \n    /// After use this object is unusable and should be disposed as the\n    /// temporary file is gone; it has become the original. In the event of an\n    /// error while swapping the file, the file no longer becomes the original,\n    /// but this object still becomes unusable.\n    /// </remarks>\n    internal bool SwapWithOriginal()\n    {\n        bool success = false;\n\n        if (_original == null)\n        {\n            throw new InvalidOperationException(\n                SR.DocumentStreamMustBeTemporary);\n        }\n        if (_original._xpsFileToken == null)\n        {\n            throw new InvalidOperationException(\n                SR.DocumentStreamMustBeFileSource);\n        }\n        if (_xpsFileToken == null)\n        {\n            throw new InvalidOperationException(\n                SR.DocumentStreamMustBeFileSource);\n        }\n\n        Trace.SafeWrite(\n            Trace.File,\n            \"Begining file swap between {0} and {1}.\",\n            _xpsFileToken.Location,\n            _original._xpsFileToken.Location);\n\n        ThrowIfInvalidXpsFileForSave(_xpsFileToken.Location);\n        ThrowIfInvalidXpsFileForOpen(_original._xpsFileToken.Location);\n\n        string original = _original._xpsFileToken.Location.LocalPath;","sourceCodeStart":490,"sourceCodeEnd":526,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationUI/MS/Internal/Documents/Application/DocumentStream.cs#L490-L526","documentation":"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.","triggerScenarios":"SwapWithOriginal() called where the temporary stream is valid but its _original was created from a memory stream or non-file source (_original._xpsFileToken == null).","commonSituations":"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.","solutions":["Create the original DocumentStream from a file path (file URI) so it has an XPS file token before using swap logic.","For stream-sourced documents, persist to a temporary file first, then perform file-based operations.","Skip swap/commit operations for non-file-backed documents and handle them via an alternate save path."],"exampleFix":"// before\nvar doc = XpsDocument(... from MemoryStream ...); // later SwapWithOriginal fails\n// after\nwrite stream to temp .xps file; open DocumentStream from the file path, then swap","handlingStrategy":"validation","validationCode":"bool originalIsFileBacked = docStream.Original != null && docStream.Original.Location != null && docStream.Original.Location.IsFile;","typeGuard":null,"tryCatchPattern":"try { docStream.SwapWithOriginal(); }\ncatch (InvalidOperationException) { /* persist stream to temp file, retry */ }","preventionTips":["Create originals from file URIs; persist in-memory XPS to a temp file before file-based operations.","Route stream-sourced documents to stream-based save paths."],"tags":["xps","invalid-operation","stream","file"],"backgroundTag":"incompatible-source-type","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}