{"record":{"id":"9ecee4291a479767","repo":"dotnet/wpf","slug":"sr-packagingwriteabledelegategavenullpart","errorCode":null,"errorMessage":"SR.PackagingWriteableDelegateGaveNullPart","messagePattern":"SR\\.PackagingWriteableDelegateGaveNullPart","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationUI/MS/Internal/Documents/Application/WriteableOnDemandPackagePart.cs","lineNumber":192,"sourceCode":"    /// <param name=\"mode\">Desired FileMode.</param>\n    /// <param name=\"access\">Desired FileAccess.</param>\n    /// <returns>A writeable stream.</returns>\n    private Stream WriteableStreamFactory(\n        FileMode mode,\n        FileAccess access)\n    {\n        if (!_isActiveWriteable)\n        {\n            Trace.SafeWrite(\n                Trace.Packaging,\n                \"Creating a writeable stream for {0} with {1} access\",\n                _activePart.Uri,\n                access);\n\n            PackagePart writingPart = _getWriteablePartInstance(this);\n            if (writingPart == null)\n            {\n                throw new IOException(\n                    SR.PackagingWriteableDelegateGaveNullPart);\n            }\n\n            if (writingPart.Equals(this))\n            {\n                throw new IOException(\n                    SR.PackagingCircularReference);\n            }\n\n            _activePart = writingPart;\n            _isActiveWriteable = true;\n        }\n\n        return _activePart.GetStream(mode, access);\n    }\n    #endregion Private Methods\n\n    #region Private Fields","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationUI/MS/Internal/Documents/Application/WriteableOnDemandPackagePart.cs#L174-L210","documentation":"WriteableOnDemandPackagePart.WriteableStreamFactory asks a user-supplied delegate (_getWriteablePartInstance) for the actual PackagePart to write into, and the delegate returned null. The library throws IOException because it cannot proceed with a lazy writeable part without a concrete backing part.","triggerScenarios":"Calling Write/SetLength on a WriteableOnDemandPackagePart's stream triggers EnsureWritable -> _writeableStreamFactory(mode, access); the registered delegate callback returns null instead of a PackagePart instance.","commonSituations":"Custom XPS document assembly/deferred-save code where the delegate that instantiates the real part fails to find or create the part (e.g. part already disposed, package closed, delegate logic returning null on error paths instead of throwing).","solutions":["Fix the _getWriteablePartInstance delegate so it always returns a valid PackagePart or throws a descriptive exception instead of returning null.","Verify the underlying package is still open and the part Uri/access requested are valid when the delegate runs.","Guard the write path: only write to the on-demand stream after confirming the delegate can produce the part."],"exampleFix":"// before\nPackagePart GetWritablePart(WriteableOnDemandPackagePart p)\n{\n    if (_package == null) return null; // causes IOException\n    return _package.GetPart(p.Uri);\n}\n// after\nPackagePart GetWritablePart(WriteableOnDemandPackagePart p)\n{\n    if (_package == null)\n        throw new IOException(\"Package already closed; cannot create writeable part for \" + p.Uri);\n    return _package.GetPart(p.Uri);\n}","handlingStrategy":"validation","validationCode":"if (_package == null || _package.FileOpenAccess != FileAccess.ReadWrite)\n    throw new IOException(\"Package must be open for ReadWrite before writeable part can be created.\");","typeGuard":"bool CanProvideWritablePart(Func<PackagePart> factory) { try { return factory?.Invoke() != null; } catch { return false; } }","tryCatchPattern":"try { stream.Write(data, 0, data.Length); }\ncatch (IOException ex) when (ex.Message.Contains(\"WriteableDelegate\"))\n{ Log.Error(\"Part delegate returned null\", ex); }","preventionTips":["Never return null from the get-writeable-part delegate; throw with context instead.","Keep the package open for the lifetime of on-demand parts.","Unit-test the delegate against closed/disposed package states."],"tags":["wpf","packaging","null-reference","io"],"backgroundTag":"null-argument","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}