{"record":{"id":"df5b4c316ba0352e","repo":"dotnet/yarp","slug":"expected-status-101-switching-protocols","errorCode":null,"errorMessage":"Expected status 101 Switching Protocols!","messagePattern":"Expected status 101 Switching Protocols!","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"testassets/TestClient/Scenarios/RawUpgradeScenario.cs","lineNumber":36,"sourceCode":"        {\n            AllowAutoRedirect = false,\n            AutomaticDecompression = DecompressionMethods.None,\n            UseCookies = false,\n            UseProxy = false\n        };\n        using var client = new HttpMessageInvoker(handler);\n        var targetUri = new Uri(new Uri(args.Target, UriKind.Absolute), \"api/rawupgrade\");\n        var stopwatch = Stopwatch.StartNew();\n        var request = new HttpRequestMessage(HttpMethod.Get, targetUri);\n        request.Headers.TryAddWithoutValidation(\"Connection\", \"upgrade\");\n        request.Version = new Version(1, 1);\n        Console.WriteLine($\"Calling {targetUri} with upgradable HTTP/1.1\");\n\n        var response = await client.SendAsync(request, cancellation);\n        Console.WriteLine($\"Received response: {(int)response.StatusCode} in {stopwatch.ElapsedMilliseconds} ms\");\n        if (response.StatusCode != HttpStatusCode.SwitchingProtocols)\n        {\n            throw new InvalidOperationException(\"Expected status 101 Switching Protocols!\");\n        }\n\n        var rawStream = await response.Content.ReadAsStreamAsync(cancellation);\n        Console.WriteLine(\"Acquired upgraded stream. Testing bidirectional echo...\");\n        stopwatch.Restart();\n        var buffer = new byte[1];\n        for (var i = 0; i <= 255; i++)\n        {\n            buffer[0] = (byte)i;\n            await rawStream.WriteAsync(buffer, cancellation);\n            var read = await rawStream.ReadAsync(buffer, cancellation);\n            if (i == 255)\n            {\n                if (read != 0)\n                {\n                    throw new Exception($\"Read {read} bytes, expected 0 after sending Goodbye.\");\n                }\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/testassets/TestClient/Scenarios/RawUpgradeScenario.cs#L18-L54","documentation":"Asserted by RawUpgradeScenario in the SampleClient. It sends an HTTP/1.1 request with Connection: upgrade to /api/rawupgrade and expects a 101 Switching Protocols response so it can take over the raw stream for a bidirectional echo test. Anything other than 101 throws InvalidOperationException, meaning the upgrade was not negotiated.","triggerScenarios":"Running SampleClient --scenario RawUpgradeScenario against a server that does not return 101 for /api/rawupgrade, or where an intermediary refuses the upgrade.","commonSituations":"Wrong --target; the rawupgrade test endpoint missing; a reverse proxy/CDN in front that downgrades or drops the Connection: upgrade header; HTTP/1.0 target that cannot switch protocols.","solutions":["Target the matching test server that implements /api/rawupgrade with a 101 response.","Ensure no intermediary strips the Connection or Upgrade headers.","Verify the request is sent as HTTP/1.1 (the scenario forces it, but a misconfigured handler could alter behavior).","Inspect the printed received status to diagnose (e.g. 200 means upgrade was ignored)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Probe upgrade support before the scenario.\nusing var probe = new HttpClient();\nvar req = new HttpRequestMessage(HttpMethod.Get, new Uri(args.Target, \"api/rawupgrade\"));\nreq.Headers.TryAddWithoutValidation(\"Connection\", \"upgrade\");\nreq.Version = new Version(1, 1);\nvar resp = await probe.SendAsync(req);\nif (resp.StatusCode != HttpStatusCode.SwitchingProtocols)\n    Console.Error.WriteLine($\"Warning: /api/rawupgrade returned {resp.StatusCode}, scenario will fail.\");","typeGuard":null,"tryCatchPattern":"try { await RawUpgradeScenario.RunAsync(client, args, cancellation); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"101 Switching Protocols\")) {\n    Console.Error.WriteLine(\"Raw upgrade not negotiated; check --target and intermediaries.\");\n    return 1;\n}","preventionTips":["Target only the test backend that returns 101 for /api/rawupgrade.","Ensure no proxy strips Connection/Upgrade headers.","Verify the request path is HTTP/1.1 as the scenario requires."],"tags":["test","http-upgrade","scenario","test-client","yarp"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}