{"record":{"id":"3250ca2bfd8f9e5a","repo":"SignalR/SignalR","slug":"negotiate-redirection-limit-exceeded","errorCode":null,"errorMessage":"Negotiate redirection limit exceeded.","messagePattern":"Negotiate redirection limit exceeded\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.AspNet.SignalR.Client/Connection.cs","lineNumber":581,"sourceCode":"                                                _actualQueryString = _userQueryString;\n                                            }\n\n                                            if (!_actualUrl.EndsWith(\"/\"))\n                                            {\n                                                _actualUrl += \"/\";\n                                            }\n\n                                            if (!string.IsNullOrEmpty(negotiationResponse.AccessToken))\n                                            {\n                                                // This will stomp on the current Authorization header, but that's by design.\n                                                // If the server specified a token, that is expected to overrule the token the client is currently using.\n                                                Headers[\"Authorization\"] = $\"Bearer {negotiationResponse.AccessToken}\";\n                                            }\n\n                                            negotiationAttempts += 1;\n                                            if (negotiationAttempts >= MaxRedirects)\n                                            {\n                                                throw new InvalidOperationException(Resources.Error_NegotiationLimitExceeded);\n                                            }\n                                            return StartNegotiation();\n                                        }\n                                    }\n\n                                    return CompleteNegotiation(negotiationResponse);\n                                })\n                                .ContinueWithNotComplete(() => Disconnect());\n            }\n\n            _connectionData = OnSending();\n\n            return StartNegotiation();\n        }\n\n        private Task StartTransport()\n        {\n            return _transport.Start(this, _connectionData, _disconnectCts.Token)","sourceCodeStart":563,"sourceCodeEnd":599,"githubUrl":"https://github.com/SignalR/SignalR/blob/693053b89a9e1f5ce819e3233ed159a6409de22b/src/Microsoft.AspNet.SignalR.Client/Connection.cs#L563-L599","documentation":"Thrown as InvalidOperationException when the number of negotiate redirects exceeds MaxRedirects (100). SignalR supports redirect responses (RedirectUrl/AccessToken) for scale-out and auth token refresh, but each redirect re-runs negotiation; the limit prevents infinite redirect loops.","triggerScenarios":"The server's negotiate endpoint repeatedly returns a RedirectUrl, causing the client to re-negotiate more than 100 times. Typically a misconfigured redirect target that points back to itself or chains endlessly.","commonSituations":"A reverse proxy or load balancer that always appends a redirect; a redirect configured to a URL that itself triggers another redirect; auth token refresh logic that always redirects; an incorrect RedirectUrl pointing back to the same negotiate endpoint.","solutions":["Inspect server-side redirect configuration and the RedirectUrl being returned; ensure it points to a final, non-redirecting endpoint.","Check that the redirect target is stable (not itself emitting a redirect).","Fix proxy/load-balancer rules so they do not redirect negotiate repeatedly.","Verify the auth flow does not force a redirect on every negotiate."],"exampleFix":"// before: server always redirects negotiate back to itself\n// after: server returns a stable RedirectUrl only once, then a final negotiation response","handlingStrategy":"try-catch","validationCode":"// client cannot pre-validate; ensure server redirect config is stable\n// verify RedirectUrl target does not itself redirect","typeGuard":null,"tryCatchPattern":"try { await connection.Start(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"redirection limit\")) {\n    logger.Error(\"Negotiate redirect loop - check server/RedirectUrl config\");\n}","preventionTips":["Ensure the server's RedirectUrl points to a final, stable endpoint.","Audit proxy/load-balancer rules so they do not redirect negotiate repeatedly.","Do not configure auth flows that force a redirect on every negotiate."],"tags":["signalr","client","negotiate","redirect","configuration","loop"],"backgroundTag":null,"analyzedSha":"693053b89a9e1f5ce819e3233ed159a6409de22b","analyzedAt":"2026-08-13T22:23:59.793Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}