dotnet/aspnetcore · error · Error
A reconnectPolicy has already been set.
Error message
A reconnectPolicy has already been set.
What it means
Thrown at HubConnectionBuilder.ts:180 by `withAutomaticReconnect()` if `this.reconnectPolicy` is already set. The builder enforces single configuration of the reconnect policy to avoid ambiguity about which policy wins; calling withAutomaticReconnect twice (in any overload form) trips the guard.
Source
Thrown at src/SignalR/clients/ts/signalr/src/HubConnectionBuilder.ts:180
* By default, the client will wait 0, 2, 10 and 30 seconds respectively before trying up to 4 reconnect attempts.
*/
public withAutomaticReconnect(): HubConnectionBuilder;
/** Configures the {@link @microsoft/signalr.HubConnection} to automatically attempt to reconnect if the connection is lost.
*
* @param {number[]} retryDelays An array containing the delays in milliseconds before trying each reconnect attempt.
* The length of the array represents how many failed reconnect attempts it takes before the client will stop attempting to reconnect.
*/
public withAutomaticReconnect(retryDelays: number[]): HubConnectionBuilder;
/** Configures the {@link @microsoft/signalr.HubConnection} to automatically attempt to reconnect if the connection is lost.
*
* @param {IRetryPolicy} reconnectPolicy An {@link @microsoft/signalR.IRetryPolicy} that controls the timing and number of reconnect attempts.
*/
public withAutomaticReconnect(reconnectPolicy: IRetryPolicy): HubConnectionBuilder;
public withAutomaticReconnect(retryDelaysOrReconnectPolicy?: number[] | IRetryPolicy): HubConnectionBuilder {
if (this.reconnectPolicy) {
throw new Error("A reconnectPolicy has already been set.");
}
if (!retryDelaysOrReconnectPolicy) {
this.reconnectPolicy = new DefaultReconnectPolicy();
} else if (Array.isArray(retryDelaysOrReconnectPolicy)) {
this.reconnectPolicy = new DefaultReconnectPolicy(retryDelaysOrReconnectPolicy);
} else {
this.reconnectPolicy = retryDelaysOrReconnectPolicy;
}
return this;
}
/** Configures {@link @microsoft/signalr.HubConnection.serverTimeoutInMilliseconds} for the {@link @microsoft/signalr.HubConnection}.
*
* @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.
*/
public withServerTimeout(milliseconds: number): HubConnectionBuilder {View on GitHub (pinned to 294cab2f9b)
Solutions
- Call `withAutomaticReconnect` exactly once per builder instance.
- If you need to change policy, build a new HubConnectionBuilder.
- Refactor shared setup functions to be idempotent — track whether they already configured reconnect.
- Pick the single most-appropriate overload (no-arg default, delays array, or custom policy) and use only that.
Example fix
// before builder.withAutomaticReconnect([0, 2000, 10000]).withAutomaticReconnect(); // throws // after builder.withAutomaticReconnect([0, 2000, 10000]); // or for full default builder.withAutomaticReconnect();
Defensive patterns
Strategy: validation
Validate before calling
function withReconnect(builder, policy) {
if (builder.reconnectPolicy) {
throw new Error('reconnectPolicy already configured on this builder');
}
return builder.withAutomaticReconnect(policy);
} Type guard
function builderHasReconnect(b: HubConnectionBuilder): boolean {
return !!(b as any).reconnectPolicy;
} Try / catch
try { builder.withAutomaticReconnect(policy); }
catch (e) {
if (/reconnectPolicy has already been set/.test(String(e))) {
// already configured - skip silently or build a new builder
return builder;
}
throw e;
} Prevention
- Call withAutomaticReconnect exactly once per builder.
- Make shared setup helpers idempotent (track a flag).
- Use a fresh builder when you need a different policy.
When it happens
Trigger: Calling `builder.withAutomaticReconnect()` twice in a chain; calling `withAutomaticReconnect()` then `withAutomaticReconnect([0, 2000, 10000])`; calling `withAutomaticReconnect(policy)` after the no-arg overload; a config helper that adds a reconnect policy unconditionally and is then called again by app code.
Common situations: A shared builder-setup function that adds reconnect, then app code adds it again; iterating on config without realizing the builder is stateful; copy-paste between files leaving a duplicate call; conditional setup where both branches run.
Related errors
- Unknown log level: ${name}
- The 'HubConnectionBuilder.withUrl' method must be called bef
- EqualTo validator requires a non-empty "other" parameter.
- FileExtensions validator requires a non-empty "extensions" p
- Range validator requires at least one of "min" or "max" para
AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06).
Data as JSON: /api/errors/ab89aa20190d18c1.
Report an issue: GitHub.