dotnet/wpf · error · IOException
SR.PackagingCircularReference
Error message
SR.PackagingCircularReference
What it means
WriteableOnDemandStream.EnsureWritable rejects a writer stream that equals the on-demand stream itself (writer.Equals(this)); redirecting the active stream to itself would recurse forever. IOException(PackagingCircularReference) is thrown.
Solutions
- Make the factory return a fresh/independent underlying Stream, never the WriteableOnDemandStream instance itself.
- Review stream caching logic so cached streams are the raw storage streams, not the wrapper.
- Add a debug assert in the factory comparing the returned stream against the wrapper.
Example fix
// before Stream Factory(FileMode m, FileAccess a) => this; // circular // after Stream Factory(FileMode m, FileAccess a) => _part.GetStream(m, a);
Defensive patterns
Strategy: validation
Validate before calling
Stream writer = CreateWriterStream();
if (ReferenceEquals(writer, onDemandStream))
throw new InvalidOperationException("Factory returned the on-demand stream itself."); Type guard
bool IsIndependent(Stream requested, Stream returned) => !ReferenceEquals(returned, requested);
Try / catch
try { stream.Write(data, 0, data.Length); }
catch (IOException ex) when (ex.Message.Contains("CircularReference"))
{ Log.Error("Stream factory returned wrapper stream", ex); } Prevention
- Return raw storage streams from the factory, never the wrapper.
- Cache only underlying streams.
- Add asserts against self-return.
When it happens
Trigger: Write/SetLength on a WriteableOnDemandStream whose factory delegate returns the same stream instance it manages, instead of an independent underlying stream.
Common situations: Factory implementation that caches and returns 'this' or a stream that wraps nothing, typically a copy-paste bug in custom package part implementations.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- SR.PackagingCircularReference
- SR.PackagingWriteableDelegateGaveNullPart
- SR.PackagingWriteableDelegateGaveNullStream
- SR.ReadNotSupported
- ' ' cannot contain the path delimiter: ' '.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/33d1bc192bac04c4.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationUI/MS/Internal/Documents/Application/WriteableOnDemandStream.cs:293
{
if (!_wantedWrite)
{
throw new NotSupportedException(
SR.PackagingWriteNotSupported);
}
if (!_isActiveWriteable)
{
Stream writer = _writeableStreamFactory(_mode, _access);
if (writer == null)
{
throw new IOException(
SR.PackagingWriteableDelegateGaveNullStream);
}
if (writer.Equals(this))
{
throw new IOException(
SR.PackagingCircularReference);
}
writer.Position = _active.Position;
_active = writer;
_isActiveWriteable = true;
}
}
#endregion Private Methods
#region Private Fields
//--------------------------------------------------------------------------
// Private Fields
//--------------------------------------------------------------------------
/// <summary>
/// The delegate we were given to have a writeable stream created.View on GitHub (pinned to 81131a70a4)