dotnet/aspnetcore · error · Error
Unexpected status code returned from authentication refresh
Error message
Unexpected status code returned from authentication refresh '${response.statusCode}' What it means
Thrown at HttpConnection.ts:436 when the POST to the `/refresh` endpoint returns any HTTP status other than 200. The refresh protocol expects a 200 with a JSON body containing accessToken and tokenLifetimeSeconds; any other status is treated as a failed refresh and the new token is not applied.
Source
Thrown at src/SignalR/clients/ts/signalr/src/HttpConnection.ts:436
const connectionGeneration = this._connectionGeneration;
const headers: {[k: string]: string} = {};
const [name, value] = getUserAgentHeader();
headers[name] = value;
const refreshUrl = this._createRefreshUrl(this._connectionUrl, this._connectionToken);
this._logger.log(LogLevel.Debug, `Sending authentication refresh request: ${refreshUrl}.`);
const request: HttpRequest = {
content: "",
headers: { ...headers, ...this._options.headers },
timeout: this._options.timeout,
withCredentials: this._options.withCredentials,
};
this._httpClient.markAuthenticationRefreshRequest(request);
const response = await this._httpClient.post(refreshUrl, request);
if (response.statusCode !== 200) {
throw new Error(`Unexpected status code returned from authentication refresh '${response.statusCode}'`);
}
if (typeof response.content !== "string") {
throw new Error("Invalid authentication refresh response received: expected JSON content.");
}
if (connectionGeneration !== this._connectionGeneration) {
return undefined;
}
const refreshResponse = JSON.parse(response.content) as { accessToken?: unknown, tokenLifetimeSeconds?: unknown };
if (typeof refreshResponse.accessToken === "string" && refreshResponse.accessToken) {
// Redirecting servers can return a transport token that should replace the current cached token.
this._setTransportAccessToken(refreshResponse.accessToken);
} else if (!this._transportAccessTokenFromServer) {
// Without a server-provided transport token, reuse the app token that successfully authenticated refresh.
const refreshRequestToken = this._httpClient.getRefreshRequestToken(response);
if (refreshRequestToken) {View on GitHub (pinned to 294cab2f9b)
Solutions
- Verify the server is running a version of ASP.NET Core SignalR that implements the authentication refresh endpoint.
- Check server logs for the failing refresh request to see the real status code and reason.
- Ensure the connection token (`id=` query param) is preserved by any proxy.
- Handle the thrown error in your refreshAuthentication catch and trigger a full reconnect with a fresh app token instead of relying on refresh.
Example fix
// before
await hub.refreshAuthentication();
// after
try {
await hub.refreshAuthentication();
} catch (e) {
console.warn('refresh failed, full reconnect', e);
await hub.stop();
// re-acquire app token, then start again
await hub.start();
} Defensive patterns
Strategy: try-catch
Validate before calling
// cannot fully pre-check (status depends on server), but you can verify // the server implements the refresh endpoint with a HEAD/GET probe.
Try / catch
try { await hub.refreshAuthentication(); }
catch (e) {
const m = /status code returned from authentication refresh '(\d+)'/.exec(String(e));
if (m) {
const code = Number(m[1]);
if (code === 401 || code === 403) {
// app token fully expired - full reconnect with fresh token
await hub.stop(); await hub.start();
} else if (code === 404) {
throw new Error('server does not implement the refresh endpoint');
}
}
throw e;
} Prevention
- Run a server version that implements the refresh endpoint.
- Ensure proxies preserve the id= query param on refresh requests.
- Schedule refreshes early enough (refreshBeforeExpirationInMilliseconds) to avoid post-expiration 401s.
When it happens
Trigger: The auth refresh token has fully expired server-side (401); the connection token is unknown to the server (404); a server error (500); a proxy returning 403/502; the refresh endpoint not being implemented on the server (404) when using an older server version.
Common situations: Server clock skew causing the refresh to arrive after expiration; reverse proxy stripping the `id=` query param; ASP.NET Core server too old to implement the refresh endpoint (added in a later version); app token revoked out-of-band.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Could not load settings from '${settings.configurationEndpoi
- The server responded with status ${response.status}.
- Cannot refresh authentication before the connection is start
- Invalid authentication refresh response received: expected J
- Cannot refresh authentication when the connection is not act
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/7b7735c99ec5a3d4.
Report an issue: GitHub.