dotnet/wpf · error · IOException

Cannot create a stream in a read-only package.

Error message

Cannot create a stream in a read-only package.

What it means

StreamInfo.Create/GetStream calls CreateTimeReadOnlyCheck before creating a new stream in the compound file. If the root storage was opened with FileAccess.Read, no new stream can be created, so an IOException is thrown. This is a deliberate write-attempt-on-read-only-container guard.

Solutions

  1. Open the root storage/Package with FileAccess.ReadWrite or FileAccess.Write instead of FileAccess.Read
  2. Check parentStorage.Root.OpenAccess before calling Create and open a new writable instance
  3. If only reading is intended, use GetStream instead of Create and avoid mutating APIs

Example fix

// before
var package = Package.Open(path, FileMode.Open, FileAccess.Read);
package.CreatePart(uri, mime); // throws
// after
var package = Package.Open(path, FileMode.Open, FileAccess.ReadWrite);
package.CreatePart(uri, mime);
Defensive patterns

Strategy: validation

Validate before calling

if (root.OpenAccess == FileAccess.Read)
    throw new InvalidOperationException("Package opened read-only; cannot create streams.");

Try / catch

try { streamInfo.Create(name, FileMode.Create, FileAccess.ReadWrite); }
catch (IOException ex) when (ex.Message.Contains("read-only")) { /* open writable instead */ }

Prevention

When it happens

Trigger: Calling StreamInfo.Create or StreamInfo.GetStream on a storage whose root was opened read-only (OpenAccess == FileAccess.Read), e.g. after StorageRoot.Open(path, FileMode.Open, FileAccess.Read) or via Package.Open with read access.

Common situations: Opening a .docx/.xlsx compound package in read-only mode then attempting to add a part; opening files from read-only media or a downloaded file left with read-only attribute but still calling write APIs.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/WindowsBase/System/IO/Packaging/CompoundFile/StreamInfo.cs:566

            }
            else
            {
                // Pass raw stream to data space manager to get real stream
               return parentStorage.Root.GetDataSpaceManager().CreateDataSpaceStream(
                    StreamReference, rawStream);
            }
        }

        /// <summary>
        /// A check against FileAccess.Read at create time.  It should fail if
        ///  the root container is read-only, or if we're pointlessly trying
        ///  to create a read-only stream.
        /// </summary>
        private void CreateTimeReadOnlyCheck( FileAccess access )
        {
            // Can't create a stream if the root container is read-only
            if( FileAccess.Read == parentStorage.Root.OpenAccess )
                throw new IOException(
                    SR.CanNotCreateInReadOnly);

            // Doesn't make sense to create a new stream just to make it read-only
            if( access == FileAccess.Read )
                throw new ArgumentException(
                    SR.CanNotCreateAsReadOnly);
        }

        /// <summary>
        /// Shortcut macro - calls the IStorage::CreateStream method on the parent
        /// storage object.
        /// </summary>
        private IStream CreateStreamOnParentIStorage(
            string name, 
            int mode )
        {
            IStream createdStream = null;
            int nativeCallErrorCode = 0;

View on GitHub (pinned to 81131a70a4)