-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Undocumented breaking change in .NET 10: System.IO.Packaging.Package disposal causes "Package object was closed and disposed" error with DocumentFormat.OpenXml #126465
Description
Description
FYI, this is a summary generated by copilot, I'll try to copy/paste only the relevant information:
Summary
After upgrading from .NET 8 to .NET 10, code using DocumentFormat.OpenXml (version 3.5.1, previously version: 3.3.0) with System.IO.Packaging.Package throws InvalidOperationException: "Package object was closed and disposed, so cannot carry out operations on this object or any stream opened on a part of this package." during document disposal.
This appears to be an undocumented breaking change in .NET 10's disposal behavior that is not listed in the official breaking changes documentation: https://learn.microsoft.com/en-us/dotnet/core/compatibility/10
Environment
• .NET Version: .NET 10.0
• OS: Windows
• Visual Studio: 2026 (18.5.0-insiders)
• DocumentFormat.OpenXml: 3.5.1
• Previous working version: .NET 8 with \OpenXml library v: 3.3.0
Reproduction Steps
Code that worked in .NET 8:
public byte[] Export(string fileTemplate, string fileName, Func<string, string> Replace)
{
string filePath = System.IO.Path.Combine(Directory.GetCurrentDirectory(), "Data/");
var fileTemp = filePath + fileTemplate;
using var stream = new MemoryStream(System.IO.File.ReadAllBytes(fileTemp), true);
using var wordDoc = WordprocessingDocument.Open(stream, true);
string docText = "";
if (wordDoc != null && wordDoc.MainDocumentPart != null)
{
XmlDocument doc = new XmlDocument();
var s = wordDoc.MainDocumentPart.GetStream(FileMode.OpenOrCreate, FileAccess.ReadWrite);
doc.Load(s);
docText = doc.OuterXml;
s.Seek(0, SeekOrigin.Begin);
docText = Replace.Invoke(docText);
doc.LoadXml(docText);
doc.Save(s);
wordDoc.Save();
}
return stream.ToArray();
}
Expected behavior
Code should work as it did in .NET 8, with the document being saved and the byte array returned successfully.
Actual behavior
Exception thrown during wordDoc.Dispose():
System.InvalidOperationException: Package object was closed and disposed, so cannot carry out operations on this object or any stream opened on a part of this package.
at System.IO.Packaging.Package.ThrowIfObjectDisposed()
at System.IO.Packaging.Package.get_FileOpenAccess()
at DocumentFormat.OpenXml.Features.PackageFeatureBase.DocumentFormat.OpenXml.Packaging.IPackage.get_FileOpenAccess()
at DocumentFormat.OpenXml.Packaging.Builder.DelegatingPackageFeature.get_FileOpenAccess()
at DocumentFormat.OpenXml.Packaging.Builder.DelegatingPackageFeature.get_FileOpenAccess()
at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.SavePartContents(Boolean save)
at DocumentFormat.OpenXml.Packaging.OpenXmlPackage.Dispose(Boolean disposing)
Regression?
Yes, it worked on .NET 8, OpenXML 3.3.0
Known Workarounds
Root Cause Analysis
The disposal behavior of System.IO.Packaging.Package appears to have changed in .NET 10. When using using var for both the MemoryStream and WordprocessingDocument, the underlying Package is disposed before the WordprocessingDocument can complete its save operation during disposal.
Workaround:
public byte[] Export(string fileTemplate, string fileName, Func<string, string> Replace)
{
string filePath = System.IO.Path.Combine(Directory.GetCurrentDirectory(), "Data/");
var fileTemp = filePath + fileTemplate;
using var inputStream = new MemoryStream(System.IO.File.ReadAllBytes(fileTemp));
using var outputStream = new MemoryStream();
using (var sourceDoc = WordprocessingDocument.Open(inputStream, false))
{
using var destDoc = (WordprocessingDocument)sourceDoc.Clone(outputStream, true);
if (destDoc?.MainDocumentPart != null)
{
string docText;
XmlDocument doc = new XmlDocument();
var s = destDoc.MainDocumentPart.GetStream(FileMode.OpenOrCreate, FileAccess.ReadWrite);
doc.Load(s);
docText = doc.OuterXml;
docText = Replace.Invoke(docText);
s.Seek(0, SeekOrigin.Begin);
doc.LoadXml(docText);
doc.Save(s);
}
destDoc.Save();
}
return outputStream.ToArray();
}
Configuration
No response
Other information
No response