dotnet/wpf · error · IOException
SR.PackagingWriteableDelegateGaveNullStream
Error message
SR.PackagingWriteableDelegateGaveNullStream
What it means
WriteableOnDemandStream.EnsureWritable invokes the _writeableStreamFactory delegate to obtain the real writeable stream; if the delegate returns null the lazy stream has no backing writer, so IOException(PackagingWriteableDelegateGaveNullStream) is thrown.
Solutions
- Ensure the writeable stream factory always returns a non-null Stream or throws an exception with context.
- Check that the package/part backing the stream is still open and writeable when the factory executes.
- Validate writeability (part-level checks) before beginning the deferred write flow.
Example fix
// before
Stream Factory(FileMode m, FileAccess a) => _part?.GetStream(m, a); // null when _part is null
// after
Stream Factory(FileMode m, FileAccess a)
{
if (_part == null) throw new IOException("Backing part unavailable for write");
return _part.GetStream(m, a);
} Defensive patterns
Strategy: validation
Validate before calling
if (backingPart == null || !backingPart.FileOpenAccess.HasFlag(FileAccess.Write))
throw new IOException("Backing part unavailable or not writeable for on-demand stream."); Type guard
bool CanProvideWritableStream(Func<FileMode, FileAccess, Stream> f)
{ try { return f?.Invoke(FileMode.OpenOrCreate, FileAccess.Write) != null; } catch { return false; } } Try / catch
try { stream.Write(data, 0, data.Length); }
catch (IOException ex) when (ex.Message.Contains("GaveNullStream"))
{ Log.Error("Stream factory returned null", ex); } Prevention
- Factory must throw, never return null.
- Validate backing part lifetime before deferred writes.
- Test the factory after package close/dispose.
When it happens
Trigger: First Write or SetLength call on an on-demand stream that is not yet actively writeable, where the registered WriteableStreamFactory callback returns null instead of a Stream.
Common situations: Deferred-save XPS scenarios where the factory's part creation failed silently (package disposed, part missing) and the error path returned null rather than throwing.
Related errors
- SR.PackagingWriteableDelegateGaveNullPart
- SR.PackagingCircularReference
- SR.PackagingCircularReference
- SR.ReadNotSupported
- ' ' cannot contain the path delimiter: ' '.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/293e0adabcea1d49.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationUI/MS/Internal/Documents/Application/WriteableOnDemandStream.cs:287
/// Ensures either the active stream is our writeable stream or uses the
/// factory delegate to get one and assign it as the active stream.
/// </summary>
/// <exception cref="System.IO.IOException" />
/// <exception cref="System.NotSupportedException" />
private void EnsureWritable()
{
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 FieldsView on GitHub (pinned to 81131a70a4)