{"record":{"id":"8f06fd7f4d8d1b2a","repo":"JeffreySu/WeiXinMPSDK","slug":"argumentnullexception-destination-is-null","errorCode":null,"errorMessage":"ArgumentNullException (destination is null)","messagePattern":"ArgumentNullException \\(destination is null\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/MsgAudit/MsgAuditFinanceClient.cs","lineNumber":205,"sourceCode":"\n        /// <summary>\n        /// 连续下载会话媒体文件的全部分片并写入目标流。\n        /// </summary>\n        /// <param name=\"sdkFileId\">解密后消息 JSON 中的 <c>sdkfileid</c>。</param>\n        /// <param name=\"destination\">可写的目标流；本方法不会关闭该流。</param>\n        /// <param name=\"cancellationToken\">在每个原生分片请求前检查的取消令牌。</param>\n        /// <returns>写入目标流的总字节数。</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"destination\"/> 为空。</exception>\n        /// <exception cref=\"ArgumentException\"><paramref name=\"sdkFileId\"/> 为空。</exception>\n        /// <exception cref=\"ArgumentException\"><paramref name=\"destination\"/> 不可写。</exception>\n        /// <exception cref=\"InvalidDataException\">原生 SDK 未完成下载但没有返回可继续使用的新索引。</exception>\n        public long DownloadMedia(string sdkFileId, Stream destination,\n            CancellationToken cancellationToken = default)\n        {\n            ValidateRequiredText(sdkFileId, nameof(sdkFileId));\n            if (destination == null)\n            {\n                throw new ArgumentNullException(nameof(destination));\n            }\n\n            if (!destination.CanWrite)\n            {\n                throw new ArgumentException(\"目标流必须可写。\", nameof(destination));\n            }\n\n            var indexBuffer = string.Empty;\n            long totalBytes = 0;\n            while (true)\n            {\n                cancellationToken.ThrowIfCancellationRequested();\n                var chunk = GetMediaData(sdkFileId, indexBuffer);\n                if (chunk.data.Length > 0)\n                {\n                    destination.Write(chunk.data, 0, chunk.data.Length);\n                    totalBytes = checked(totalBytes + chunk.data.LongLength);\n                }","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/JeffreySu/WeiXinMPSDK/blob/be573f6f94bdbf718dd5f6cdecb137fbc7ff651e/src/Senparc.Weixin.Work/Senparc.Weixin.Work/AdvancedAPIs/MsgAudit/MsgAuditFinanceClient.cs#L187-L223","documentation":"DownloadMedia validates that the destination Stream is non-null before writing downloaded media chunks into it. Passing null means there is nowhere to write the media bytes, so the library fails fast with ArgumentNullException naming the 'destination' parameter instead of throwing a deeper NullReferenceException mid-download.","triggerScenarios":"Calling MsgAuditFinanceClient.DownloadMedia(sdkFileId, destination) with a null destination Stream, e.g. a stream variable that was never initialized or a method that conditionally returns null.","commonSituations":"Developers wiring the stream from a config/file-open call that returned null, refactoring code so the stream creation was removed, or calling DownloadMedia before setting up a FileStream/MemoryStream.","solutions":["Create and pass a writable Stream (e.g. new FileStream(path, FileMode.Create) or new MemoryStream()) as the second argument","Check the stream for null before calling DownloadMedia","Verify no code path assigns null to the stream variable between creation and the call"],"exampleFix":"// before\nStream target = GetStreamOrNull();\nlong n = client.DownloadMedia(sdkFileId, target);\n// after\nusing Stream target = GetStreamOrNull() ?? throw new InvalidOperationException(\"media stream not initialized\");\nlong n = client.DownloadMedia(sdkFileId, target);","handlingStrategy":"validation","validationCode":"if (destination == null) throw new ArgumentNullException(nameof(destination));\nif (destination is null) { /* create or obtain a writable stream */ destination = new MemoryStream(); }","typeGuard":"bool HasWritableStream(Stream? s) => s is { CanWrite: true };","tryCatchPattern":"try { client.DownloadMedia(sdkFileId, stream); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"destination\") { /* initialize stream and retry */ }","preventionTips":["Always create the destination stream immediately before the call","Use using declarations so stream lifetime is tied to the download scope","Never pass streams returned from methods that can return null without a null check"],"tags":["csharp","argument-null","stream","weixin-work"],"backgroundTag":"null-argument","analyzedSha":"be573f6f94bdbf718dd5f6cdecb137fbc7ff651e","analyzedAt":"2026-09-12T10:01:50.733Z","contentChangedAt":"2026-09-12T10:01:50.733Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}