SignalR/SignalR · error · InvalidOperationException
Negotiate redirection limit exceeded.
Error message
Negotiate redirection limit exceeded.
What it means
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.
Source
Thrown at src/Microsoft.AspNet.SignalR.Client/Connection.cs:581
_actualQueryString = _userQueryString;
}
if (!_actualUrl.EndsWith("/"))
{
_actualUrl += "/";
}
if (!string.IsNullOrEmpty(negotiationResponse.AccessToken))
{
// This will stomp on the current Authorization header, but that's by design.
// If the server specified a token, that is expected to overrule the token the client is currently using.
Headers["Authorization"] = $"Bearer {negotiationResponse.AccessToken}";
}
negotiationAttempts += 1;
if (negotiationAttempts >= MaxRedirects)
{
throw new InvalidOperationException(Resources.Error_NegotiationLimitExceeded);
}
return StartNegotiation();
}
}
return CompleteNegotiation(negotiationResponse);
})
.ContinueWithNotComplete(() => Disconnect());
}
_connectionData = OnSending();
return StartNegotiation();
}
private Task StartTransport()
{
return _transport.Start(this, _connectionData, _disconnectCts.Token)View on GitHub (pinned to 693053b89a)
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.
Example fix
// before: server always redirects negotiate back to itself // after: server returns a stable RedirectUrl only once, then a final negotiation response
Defensive patterns
Strategy: try-catch
Validate before calling
// client cannot pre-validate; ensure server redirect config is stable // verify RedirectUrl target does not itself redirect
Try / catch
try { await connection.Start(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("redirection limit")) {
logger.Error("Negotiate redirect loop - check server/RedirectUrl config");
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Url cannot contain query string directly. Pass query string
- The connection was stopped before it could be started.
- Error message received from the server: '{0}'.
- You are using a version of the client that isn't compatible
- SignalR: Error loading hubs. Ensure your hubs reference is c
AI-assisted analysis of SignalR/SignalR@693053b89a (2026-08-13).
Data as JSON: /api/errors/3250ca2bfd8f9e5a.
Report an issue: GitHub.