{"record":{"id":"3605934f388e543f","repo":"SignalR/SignalR","slug":"response","errorCode":null,"errorMessage":"response","messagePattern":"response","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.AspNet.SignalR.Client/Http/IResponseExtensions.cs","lineNumber":18,"sourceCode":"// Copyright (c) .NET Foundation. All rights reserved.\n// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.\n\nusing System;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Microsoft.AspNet.SignalR.Client.Transports;\nusing Microsoft.AspNet.SignalR.Infrastructure;\n\nnamespace Microsoft.AspNet.SignalR.Client.Http\n{\n    public static class IResponseExtensions\n    {\n        public static Task<string> ReadAsString(this IResponse response, Func<ArraySegment<byte>, bool> onChunk)\n        {\n            if (response == null)\n            {\n                throw new ArgumentNullException(\"response\");\n            }\n\n            var stream = response.GetStream();\n            var reader = new AsyncStreamReader(stream);\n            var result = new StringBuilder();\n            var resultTcs = new DispatchingTaskCompletionSource<string>();\n\n            reader.Data = buffer =>\n            {\n                if (onChunk(buffer))\n                {\n                    result.Append(Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count));\n                }\n            };\n\n            reader.Closed = exception =>\n            {\n                response.Dispose();","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/SignalR/SignalR/blob/693053b89a9e1f5ce819e3233ed159a6409de22b/src/Microsoft.AspNet.SignalR.Client/Http/IResponseExtensions.cs#L1-L36","documentation":"IResponseExtensions.ReadAsString throws ArgumentNullException('response') if the IResponse is null. It then opens the response stream and reads UTF-8 chunks, invoking the onChunk predicate for each. A null response indicates the upstream Get/Post never produced a response, which is itself a deeper bug — the guard prevents a NullReferenceException inside the stream reader.","triggerScenarios":"Calling response.ReadAsString(onChunk) on a null IResponse; a custom transport returning null from Get/Post; test harness passing null.","commonSituations":"Custom transport implementation that does not return an IResponse; test double not set up; logic that discards a null response and still tries to read it.","solutions":["Only call ReadAsString on a response you have verified is non-null (from a successful Get/Post).","Fix the upstream transport so it never returns null.","In tests, supply a stub IResponse whose GetStream returns a readable stream."],"exampleFix":"// before\nvar body = await response.ReadAsString(onChunk); // response null\n// after\nif (response == null) throw new InvalidOperationException(\"No response from transport\");\nvar body = await response.ReadAsString(onChunk);","handlingStrategy":"validation","validationCode":"if (response == null) throw new InvalidOperationException(\"transport returned no response\");\nvar body = await response.ReadAsString(onChunk);","typeGuard":"static bool HasResponse(IResponse r) => r != null;","tryCatchPattern":null,"preventionTips":["Only call ReadAsString on a response from a successful Get/Post.","Fix upstream transports so they never return null.","In tests, supply a stub IResponse with a readable stream."],"tags":["signalr","http-client","response","argument-validation","null-check","streaming"],"backgroundTag":null,"analyzedSha":"693053b89a9e1f5ce819e3233ed159a6409de22b","analyzedAt":"2026-08-13T22:23:59.793Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}