dotnet/wpf · error · XpsPackagingException
Only writers can call this method.
Error message
Only writers can call this method.
What it means
XpsManager.GeneratePart refuses to run when the XpsManager was not opened in writer mode. Only the instance designated as the package writer may add parts to the XPS package; all other instances (readers) throw XpsPackagingException with SR.ReachPackaging_OnlyWriters. This enforces single-writer access to the underlying Package.
Solutions
- Open the XpsDocument/XpsManager in write mode so IsWriter is true (pass true for the writer/editable argument when constructing the XpsDocument).
- Check xpsManager.IsWriter before calling GeneratePart and route write operations to the instance that owns write access.
- Ensure the underlying file/stream is writable; open a new writable stream if the source was read-only.
- Verify only one writer instance exists and write calls are not accidentally made on a reader obtained from GetXpsDocument/Packaging conversions.
Example fix
// before
var doc = new XpsDocument(pkgPath, FileAccess.Read);
var part = xpsManager.GeneratePart(partUri, contentType, compressionOption);
// after
var doc = new XpsDocument(pkgPath, FileAccess.ReadWrite);
if (!xpsManager.IsWriter) throw new InvalidOperationException("This XpsManager is read-only");
var part = xpsManager.GeneratePart(partUri, contentType, compressionOption); Defensive patterns
Strategy: validation
Validate before calling
if (xpsManager == null || xpsManager.IsDisposed) throw new ObjectDisposedException(nameof(xpsManager));
if (!xpsManager.IsWriter) throw new InvalidOperationException("GeneratePart requires an XpsManager opened in writer mode."); Type guard
bool CanWrite(XpsManager m) => m is { IsWriter: true }; Try / catch
try { var part = xpsManager.GeneratePart(partUri, contentType, compressionOption); }
catch (XpsPackagingException ex) when (ex.Message.Contains("writers")) { /* route to writer instance or reopen writable */ } Prevention
- Always open the XpsDocument with FileAccess.ReadWrite or a write stream when mutations are planned.
- Expose a single writer instance and perform all part additions through it.
- Assert IsWriter at the start of write-path helper methods.
When it happens
Trigger: Calling GeneratePart on an XpsManager whose IsWriter property is false — i.e. an XpsDocument opened with the writer parameter false or obtained for read-only access — while trying to add a part with a given partUri and contentType.
Common situations: Opening an XpsDocument for read access (e.g. to inspect fixed documents) and then attempting to add resources or parts; sharing one package between a reader and expecting it to also write; opening the document from a read-only file/stream so the writer flag could not be set.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Document PackagePart URI is not valid.
- Package must contain an XPS PackagePart.
- PackagePart already has associated Thumbnail.
- PackagePart URI does not correspond to a FixedDocument.
- ReachPackaging_OpenDocOrElementAlreadyCalled
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/cd5bf5710eaa342b.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/ReachFramework/Packaging/XpsManager.cs:295
#endregion Public properties
#region Public methods
/// <summary>
/// Generate a unique Part for the content type and add it to the package.
/// Adding to any relationships or selector/sequence markup is not done.
/// </summary>
public
PackagePart
GeneratePart(
ContentType contentType,
Uri partUri
)
{
ObjectDisposedException.ThrowIf(_metroPackage is null, typeof(XpsManager));
if (!IsWriter)
{
throw new XpsPackagingException(SR.ReachPackaging_OnlyWriters);
}
ArgumentNullException.ThrowIfNull(contentType);
if (0 == contentType.ToString().Length)
{
throw new ArgumentException(SR.Format(SR.ReachPackaging_InvalidContentType, contentType), nameof(contentType));
}
//Do not compress image Content Types
CompressionOption compressionOption = _compressionOption;
if (contentType.AreTypeAndSubTypeEqual(XpsS0Markup.JpgContentType) ||
contentType.AreTypeAndSubTypeEqual(XpsS0Markup.PngContentType) ||
contentType.AreTypeAndSubTypeEqual(XpsS0Markup.TifContentType) ||
contentType.AreTypeAndSubTypeEqual(XpsS0Markup.WdpContentType))
{
compressionOption = CompressionOption.NotCompressed;
}
View on GitHub (pinned to 81131a70a4)