dotnet/wpf · error · IOException

SR.ReachPackaging_CannotModifyReadOnlyContainer

Error message

SR.ReachPackaging_CannotModifyReadOnlyContainer

What it means

The static method in XpsManager that writes a starting-part relationship checks package.FileOpenAccess first; if the package was opened with FileAccess.Read, it throws IOException(SR.ReachPackaging_CannotModifyReadOnlyContainer) because establishing a new starting-part relationship mutates the package.

Solutions

  1. Open the XpsDocument/package with FileAccess.ReadWrite so the container is writable.
  2. Do not call starting-part modification APIs when the package is read-only; skip the modification.
  3. If the source is read-only, copy the package to a writable stream/file first, then open ReadWrite and modify.

Example fix

// before
var doc = new XpsDocument(path, FileAccess.Read);
SetStartingPart(doc.Package, startingPart);
// after
var doc = new XpsDocument(path, FileAccess.ReadWrite);
SetStartingPart(doc.Package, startingPart);
Defensive patterns

Strategy: type-guard

Validate before calling

if (package.FileOpenAccess == FileAccess.Read) { /* skip modification or reopen writable */ }

Type guard

bool CanModify(Package p) => p.FileOpenAccess != FileAccess.Read;

Try / catch

catch (IOException) { /* package is read-only: reopen with FileAccess.ReadWrite */ }

Prevention

When it happens

Trigger: Calling the XpsManager API that registers/replaces a starting part (SetStartingPart-style path) on a package opened read-only, i.e. XpsDocument opened with FileAccess.Read or FileOpenAccess.Read.

Common situations: Loading an XPS document from a read-only stream or file (e.g. a resource or network share) and then attempting to modify its structure; viewing code that inadvertently calls a mutating API on a read-open document.

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


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/ReachFramework/Packaging/XpsManager.cs:1462

        internal
        static
        void
        SetXpsDocumentStartingPart(
            Package         package,
            PackagePart     startingPart
            )
        {
            Debug.Assert(package != null, "package cannot be null");

            //
            // null is a valid value for startingPart; it will effectively remove starting part
            // relationship to the existing starting Part; However, the existing startingPart
            // won't be removed from the package
            //

            if (package.FileOpenAccess == FileAccess.Read)
            {
                throw new IOException(SR.ReachPackaging_CannotModifyReadOnlyContainer);
            }

            //
            // Throw If the part provided is null
            //
            ArgumentNullException.ThrowIfNull(startingPart);

            //
            // Throw If the part provided is from a different container
            //
            if (startingPart.Package != package)
            {
                throw new ArgumentException(SR.ReachPackaging_PartFromDifferentContainer);
            }

                package.CreateRelationship(startingPart.Uri, TargetMode.Internal, XpsS0Markup.ReachPackageStartingPartRelationshipType);
        }

View on GitHub (pinned to 81131a70a4)