{"record":{"id":"ab89aa20190d18c1","repo":"dotnet/aspnetcore","slug":"a-reconnectpolicy-has-already-been-set","errorCode":null,"errorMessage":"A reconnectPolicy has already been set.","messagePattern":"A reconnectPolicy has already been set\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/SignalR/clients/ts/signalr/src/HubConnectionBuilder.ts","lineNumber":180,"sourceCode":"     * By default, the client will wait 0, 2, 10 and 30 seconds respectively before trying up to 4 reconnect attempts.\n     */\n    public withAutomaticReconnect(): HubConnectionBuilder;\n\n    /** Configures the {@link @microsoft/signalr.HubConnection} to automatically attempt to reconnect if the connection is lost.\n     *\n     * @param {number[]} retryDelays An array containing the delays in milliseconds before trying each reconnect attempt.\n     * The length of the array represents how many failed reconnect attempts it takes before the client will stop attempting to reconnect.\n     */\n    public withAutomaticReconnect(retryDelays: number[]): HubConnectionBuilder;\n\n    /** Configures the {@link @microsoft/signalr.HubConnection} to automatically attempt to reconnect if the connection is lost.\n     *\n     * @param {IRetryPolicy} reconnectPolicy An {@link @microsoft/signalR.IRetryPolicy} that controls the timing and number of reconnect attempts.\n     */\n    public withAutomaticReconnect(reconnectPolicy: IRetryPolicy): HubConnectionBuilder;\n    public withAutomaticReconnect(retryDelaysOrReconnectPolicy?: number[] | IRetryPolicy): HubConnectionBuilder {\n        if (this.reconnectPolicy) {\n            throw new Error(\"A reconnectPolicy has already been set.\");\n        }\n\n        if (!retryDelaysOrReconnectPolicy) {\n            this.reconnectPolicy = new DefaultReconnectPolicy();\n        } else if (Array.isArray(retryDelaysOrReconnectPolicy)) {\n            this.reconnectPolicy = new DefaultReconnectPolicy(retryDelaysOrReconnectPolicy);\n        } else {\n            this.reconnectPolicy = retryDelaysOrReconnectPolicy;\n        }\n\n        return this;\n    }\n\n    /** Configures {@link @microsoft/signalr.HubConnection.serverTimeoutInMilliseconds} for the {@link @microsoft/signalr.HubConnection}.\n     *\n     * @returns The {@link @microsoft/signalr.HubConnectionBuilder} instance, for chaining.\n     */\n    public withServerTimeout(milliseconds: number): HubConnectionBuilder {","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/294cab2f9b2e03af6b953820c7ab497c3c8b7ad9/src/SignalR/clients/ts/signalr/src/HubConnectionBuilder.ts#L162-L198","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nbuilder.withAutomaticReconnect([0, 2000, 10000]).withAutomaticReconnect(); // throws\n\n// after\nbuilder.withAutomaticReconnect([0, 2000, 10000]);\n// or for full default\nbuilder.withAutomaticReconnect();","handlingStrategy":"validation","validationCode":"function withReconnect(builder, policy) {\n  if (builder.reconnectPolicy) {\n    throw new Error('reconnectPolicy already configured on this builder');\n  }\n  return builder.withAutomaticReconnect(policy);\n}","typeGuard":"function builderHasReconnect(b: HubConnectionBuilder): boolean {\n  return !!(b as any).reconnectPolicy;\n}","tryCatchPattern":"try { builder.withAutomaticReconnect(policy); }\ncatch (e) {\n  if (/reconnectPolicy has already been set/.test(String(e))) {\n    // already configured - skip silently or build a new builder\n    return builder;\n  }\n  throw e;\n}","preventionTips":["Call withAutomaticReconnect exactly once per builder.","Make shared setup helpers idempotent (track a flag).","Use a fresh builder when you need a different policy."],"tags":["builder","reconnect","configuration","validation"],"analyzedSha":"294cab2f9b2e03af6b953820c7ab497c3c8b7ad9","analyzedAt":"2026-08-06T20:08:02.189Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}