From 0a7d74e0f098e9aa0db766e3e87e7206725e5d32 Mon Sep 17 00:00:00 2001 From: Kian Thompson Date: Tue, 10 Mar 2026 18:07:37 -0700 Subject: [PATCH 1/4] Add configuration for retry on container creation --- .../container-definitions.legacy.beta.api.md | 1 + .../container-definitions/src/loader.ts | 11 +- .../loader/container-loader/src/container.ts | 15 ++- .../loader/driver-utils/src/runWithRetry.ts | 36 ++++++ .../src/test/runWithRetry.spec.ts | 108 ++++++++++++++++++ 5 files changed, 168 insertions(+), 3 deletions(-) diff --git a/packages/common/container-definitions/api-report/container-definitions.legacy.beta.api.md b/packages/common/container-definitions/api-report/container-definitions.legacy.beta.api.md index 9cd30d8bcdb9..37a12fdb8970 100644 --- a/packages/common/container-definitions/api-report/container-definitions.legacy.beta.api.md +++ b/packages/common/container-definitions/api-report/container-definitions.legacy.beta.api.md @@ -146,6 +146,7 @@ export interface IConnectionDetails { export interface IContainer extends IEventProvider { attach(request: IRequest, attachProps?: { deltaConnection?: "none" | "delayed"; + maxCreateRetries?: number; }): Promise; readonly attachState: AttachState; readonly audience: IAudience; diff --git a/packages/common/container-definitions/src/loader.ts b/packages/common/container-definitions/src/loader.ts index 703c80a9dad6..820b6e8e52bd 100644 --- a/packages/common/container-definitions/src/loader.ts +++ b/packages/common/container-definitions/src/loader.ts @@ -431,7 +431,16 @@ export interface IContainer extends IEventProvider { */ attach( request: IRequest, - attachProps?: { deltaConnection?: "none" | "delayed" }, + attachProps?: { + deltaConnection?: "none" | "delayed"; + /** + * Maximum number of retries when creating a new container fails with a retriable error. + * + * - The `Fluid.Container.CreateMaxRetries` feature flag takes precedence over this option. + * - If neither is set, retries will continue indefinitely (default behavior). + */ + maxCreateRetries?: number; + }, ): Promise; /** diff --git a/packages/loader/container-loader/src/container.ts b/packages/loader/container-loader/src/container.ts index f6035607f005..55ff60553c77 100644 --- a/packages/loader/container-loader/src/container.ts +++ b/packages/loader/container-loader/src/container.ts @@ -1214,7 +1214,10 @@ export class Container public readonly attach = runSingle( async ( request: IRequest, - attachProps?: { deltaConnection?: "none" | "delayed" }, + attachProps?: { + deltaConnection?: "none" | "delayed"; + maxCreateRetries?: number; + }, ): Promise => { await PerformanceEvent.timedExecAsync( this.mc.logger, @@ -1286,6 +1289,7 @@ export class Container this.service = await this.createDocumentService(createNewResolvedUrl, { mode: "attach", summary, + maxCreateRetries: attachProps?.maxCreateRetries, }); } this.storageAdapter.connectToService(this.service); @@ -1533,7 +1537,9 @@ export class Container */ private async createDocumentService( resolvedUrl: IResolvedUrl, - props: { mode: "load" } | { mode: "attach"; summary: ISummaryTree | undefined }, + props: + | { mode: "load" } + | { mode: "attach"; summary: ISummaryTree | undefined; maxCreateRetries?: number }, ): Promise { let service: IDocumentService; if (props.mode === "load") { @@ -1547,6 +1553,10 @@ export class Container service.on("metadataUpdate", this.metadataUpdateHandler); } } else { + // Feature flag takes precedence over the attach parameter. + const maxRetries = + this.mc.config.getNumber("Fluid.Container.CreateMaxRetries") ?? props.maxCreateRetries; + service = await runWithRetry( async () => this.serviceFactory.createContainer( @@ -1559,6 +1569,7 @@ export class Container this.mc.logger, { cancel: this._deltaManager.closeAbortController.signal, + maxRetries, }, // progress ); } diff --git a/packages/loader/driver-utils/src/runWithRetry.ts b/packages/loader/driver-utils/src/runWithRetry.ts index 5d5da9307dd1..e515ec8cacba 100644 --- a/packages/loader/driver-utils/src/runWithRetry.ts +++ b/packages/loader/driver-utils/src/runWithRetry.ts @@ -8,6 +8,7 @@ import { delay } from "@fluidframework/core-utils/internal"; import { DriverErrorTypes } from "@fluidframework/driver-definitions/internal"; import { isFluidError, + wrapError, type ITelemetryLoggerExt, } from "@fluidframework/telemetry-utils/internal"; @@ -45,6 +46,12 @@ export interface IProgress { * @param error - error object returned from the call. */ onRetry?(delayInMs: number, error: unknown): void; + + /** + * Maximum number of retries before giving up on a retriable error. + * If undefined, retries will continue indefinitely (default behavior). + */ + maxRetries?: number; } /** @@ -122,6 +129,35 @@ export async function runWithRetry( } numRetries++; + + // Check if max retries limit has been reached + if (progress.maxRetries !== undefined && numRetries > progress.maxRetries) { + logger.sendTelemetryEvent( + { + eventName: `${fetchCallName}_maxRetriesExceeded`, + retry: numRetries - 1, + maxRetries: progress.maxRetries, + duration: performanceNow() - startTime, + fetchCallName, + }, + error, + ); + // Wrap the original error to preserve its details while marking it non-retriable + throw wrapError( + error, + (message) => + new NonRetryableError( + `runWithRetry failed after max retries: ${message}`, + DriverErrorTypes.genericError, + { + driverVersion: pkgVersion, + fetchCallName, + maxRetries: progress.maxRetries, + }, + ), + ); + } + lastError = error; // Wait for the calculated time before retrying. retryAfterMs = calculateMaxWaitTime(retryAfterMs, error); diff --git a/packages/loader/driver-utils/src/test/runWithRetry.spec.ts b/packages/loader/driver-utils/src/test/runWithRetry.spec.ts index ce18a8334b01..9dc27ab4d0e3 100644 --- a/packages/loader/driver-utils/src/test/runWithRetry.spec.ts +++ b/packages/loader/driver-utils/src/test/runWithRetry.spec.ts @@ -221,4 +221,112 @@ describe("runWithRetry Tests", () => { assert.strictEqual((error as any).reason, "Sample abort reason"); } }); + + it("Should stop retrying after maxRetries is exceeded", async () => { + const maxRetries = 3; + let retryTimes = 0; + const api = async (): Promise => { + retryTimes += 1; + const error = new Error("Throw error"); + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access -- TODO: use a real type + (error as any).canRetry = true; + throw error; + }; + + try { + await runWithFastSetTimeout(async () => + runWithRetry(api, "test", logger, { + maxRetries, + }), + ); + assert.fail("Should not succeed"); + } catch (error) { + // Verify the wrapped error includes the original error message + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment -- TODO: use a real type + const errorMessage = (error as any).message; + assert.strictEqual(errorMessage, "runWithRetry failed after max retries: Throw error"); + // Verify the original error is preserved in the cause property + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment -- TODO: use a real type + const causeMessage = (error as any).cause?.message; + assert.strictEqual(causeMessage, "Throw error"); + } + // Initial call + maxRetries attempts + assert.strictEqual(retryTimes, maxRetries + 1, "Should retry exactly maxRetries times"); + }); + + it("Should succeed before maxRetries is exceeded", async () => { + const maxRetries = 5; + let retryTimes = 0; + const api = async (): Promise => { + retryTimes += 1; + // Succeed on the 3rd attempt (after 2 failures) + if (retryTimes < 3) { + const error = new Error("Throw error"); + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access -- TODO: use a real type + (error as any).canRetry = true; + throw error; + } + return true; + }; + + const success = await runWithFastSetTimeout(async () => + runWithRetry(api, "test", logger, { + maxRetries, + }), + ); + assert.strictEqual(success, true, "Should succeed"); + assert.strictEqual(retryTimes, 3, "Should take 3 attempts to succeed"); + }); + + it("Should retry infinitely when maxRetries is undefined", async () => { + const totalRetries = 10; + let retryTimes = 0; + const api = async (): Promise => { + retryTimes += 1; + if (retryTimes <= totalRetries) { + const error = new Error("Throw error"); + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access -- TODO: use a real type + (error as any).canRetry = true; + throw error; + } + return true; + }; + + const success = await runWithFastSetTimeout(async () => + runWithRetry(api, "test", logger, {}), + ); + assert.strictEqual(success, true, "Should succeed"); + assert.strictEqual(retryTimes, totalRetries + 1, "Should retry until success"); + }); + + it("Should fail immediately with maxRetries set to 0", async () => { + let retryTimes = 0; + const api = async (): Promise => { + retryTimes += 1; + const error = new Error("Throw error"); + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access -- TODO: use a real type + (error as any).canRetry = true; + throw error; + }; + + try { + await runWithFastSetTimeout(async () => + runWithRetry(api, "test", logger, { + maxRetries: 0, + }), + ); + assert.fail("Should not succeed"); + } catch (error) { + // Verify the wrapped error includes the original error message + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment -- TODO: use a real type + const errorMessage = (error as any).message; + assert.strictEqual(errorMessage, "runWithRetry failed after max retries: Throw error"); + // Verify the original error is preserved in the cause property + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment -- TODO: use a real type + const causeMessage = (error as any).cause?.message; + assert.strictEqual(causeMessage, "Throw error"); + } + // Only the initial call, no retries + assert.strictEqual(retryTimes, 1, "Should not retry at all"); + }); }); From ca015495f21d70fe51d7691fe24665784e6f0b49 Mon Sep 17 00:00:00 2001 From: Kian Thompson Date: Mon, 16 Mar 2026 14:22:51 -0700 Subject: [PATCH 2/4] Move retry logic to consumer of attach --- .../container-definitions.legacy.beta.api.md | 1 - .../common/container-definitions/src/loader.ts | 7 ------- packages/loader/container-loader/src/container.ts | 14 ++++++-------- 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/packages/common/container-definitions/api-report/container-definitions.legacy.beta.api.md b/packages/common/container-definitions/api-report/container-definitions.legacy.beta.api.md index 37a12fdb8970..9cd30d8bcdb9 100644 --- a/packages/common/container-definitions/api-report/container-definitions.legacy.beta.api.md +++ b/packages/common/container-definitions/api-report/container-definitions.legacy.beta.api.md @@ -146,7 +146,6 @@ export interface IConnectionDetails { export interface IContainer extends IEventProvider { attach(request: IRequest, attachProps?: { deltaConnection?: "none" | "delayed"; - maxCreateRetries?: number; }): Promise; readonly attachState: AttachState; readonly audience: IAudience; diff --git a/packages/common/container-definitions/src/loader.ts b/packages/common/container-definitions/src/loader.ts index 820b6e8e52bd..01afd00bc98b 100644 --- a/packages/common/container-definitions/src/loader.ts +++ b/packages/common/container-definitions/src/loader.ts @@ -433,13 +433,6 @@ export interface IContainer extends IEventProvider { request: IRequest, attachProps?: { deltaConnection?: "none" | "delayed"; - /** - * Maximum number of retries when creating a new container fails with a retriable error. - * - * - The `Fluid.Container.CreateMaxRetries` feature flag takes precedence over this option. - * - If neither is set, retries will continue indefinitely (default behavior). - */ - maxCreateRetries?: number; }, ): Promise; diff --git a/packages/loader/container-loader/src/container.ts b/packages/loader/container-loader/src/container.ts index 55ff60553c77..b40e91ac2e47 100644 --- a/packages/loader/container-loader/src/container.ts +++ b/packages/loader/container-loader/src/container.ts @@ -1216,7 +1216,6 @@ export class Container request: IRequest, attachProps?: { deltaConnection?: "none" | "delayed"; - maxCreateRetries?: number; }, ): Promise => { await PerformanceEvent.timedExecAsync( @@ -1289,7 +1288,6 @@ export class Container this.service = await this.createDocumentService(createNewResolvedUrl, { mode: "attach", summary, - maxCreateRetries: attachProps?.maxCreateRetries, }); } this.storageAdapter.connectToService(this.service); @@ -1537,9 +1535,7 @@ export class Container */ private async createDocumentService( resolvedUrl: IResolvedUrl, - props: - | { mode: "load" } - | { mode: "attach"; summary: ISummaryTree | undefined; maxCreateRetries?: number }, + props: { mode: "load" } | { mode: "attach"; summary: ISummaryTree | undefined }, ): Promise { let service: IDocumentService; if (props.mode === "load") { @@ -1553,9 +1549,11 @@ export class Container service.on("metadataUpdate", this.metadataUpdateHandler); } } else { - // Feature flag takes precedence over the attach parameter. - const maxRetries = - this.mc.config.getNumber("Fluid.Container.CreateMaxRetries") ?? props.maxCreateRetries; + // When RetryOnAttachFailure is enabled, use no internal retries + // The consumer will own the retry policy + const retryOnAttachFailure = + this.mc.config.getBoolean("Fluid.Container.RetryOnAttachFailure") === true; + const maxRetries = retryOnAttachFailure ? 0 : undefined; service = await runWithRetry( async () => From 83dd4d589f5b27f571dd868c195b7d6a14246b5e Mon Sep 17 00:00:00 2001 From: Kian Thompson Date: Thu, 19 Mar 2026 17:06:56 -0700 Subject: [PATCH 3/4] Cleanup --- .../loader/container-loader/src/container.ts | 6 ++---- .../loader/driver-utils/src/runWithRetry.ts | 13 ++++-------- .../src/test/runWithRetry.spec.ts | 20 ++++--------------- 3 files changed, 10 insertions(+), 29 deletions(-) diff --git a/packages/loader/container-loader/src/container.ts b/packages/loader/container-loader/src/container.ts index b40e91ac2e47..21c4d3908003 100644 --- a/packages/loader/container-loader/src/container.ts +++ b/packages/loader/container-loader/src/container.ts @@ -1214,9 +1214,7 @@ export class Container public readonly attach = runSingle( async ( request: IRequest, - attachProps?: { - deltaConnection?: "none" | "delayed"; - }, + attachProps?: { deltaConnection?: "none" | "delayed" }, ): Promise => { await PerformanceEvent.timedExecAsync( this.mc.logger, @@ -1567,8 +1565,8 @@ export class Container this.mc.logger, { cancel: this._deltaManager.closeAbortController.signal, - maxRetries, }, // progress + maxRetries, ); } return service; diff --git a/packages/loader/driver-utils/src/runWithRetry.ts b/packages/loader/driver-utils/src/runWithRetry.ts index e515ec8cacba..1d62e9cae521 100644 --- a/packages/loader/driver-utils/src/runWithRetry.ts +++ b/packages/loader/driver-utils/src/runWithRetry.ts @@ -46,12 +46,6 @@ export interface IProgress { * @param error - error object returned from the call. */ onRetry?(delayInMs: number, error: unknown): void; - - /** - * Maximum number of retries before giving up on a retriable error. - * If undefined, retries will continue indefinitely (default behavior). - */ - maxRetries?: number; } /** @@ -64,6 +58,7 @@ export async function runWithRetry( fetchCallName: string, logger: ITelemetryLoggerExt, progress: IProgress, + maxRetries?: number, ): Promise { let result: T | undefined; let success = false; @@ -131,12 +126,12 @@ export async function runWithRetry( numRetries++; // Check if max retries limit has been reached - if (progress.maxRetries !== undefined && numRetries > progress.maxRetries) { + if (maxRetries !== undefined && numRetries > maxRetries) { logger.sendTelemetryEvent( { eventName: `${fetchCallName}_maxRetriesExceeded`, retry: numRetries - 1, - maxRetries: progress.maxRetries, + maxRetries, duration: performanceNow() - startTime, fetchCallName, }, @@ -152,7 +147,7 @@ export async function runWithRetry( { driverVersion: pkgVersion, fetchCallName, - maxRetries: progress.maxRetries, + maxRetries, }, ), ); diff --git a/packages/loader/driver-utils/src/test/runWithRetry.spec.ts b/packages/loader/driver-utils/src/test/runWithRetry.spec.ts index 9dc27ab4d0e3..255d8f5d28a1 100644 --- a/packages/loader/driver-utils/src/test/runWithRetry.spec.ts +++ b/packages/loader/driver-utils/src/test/runWithRetry.spec.ts @@ -223,7 +223,6 @@ describe("runWithRetry Tests", () => { }); it("Should stop retrying after maxRetries is exceeded", async () => { - const maxRetries = 3; let retryTimes = 0; const api = async (): Promise => { retryTimes += 1; @@ -234,11 +233,7 @@ describe("runWithRetry Tests", () => { }; try { - await runWithFastSetTimeout(async () => - runWithRetry(api, "test", logger, { - maxRetries, - }), - ); + await runWithFastSetTimeout(async () => runWithRetry(api, "test", logger, {}, 3)); assert.fail("Should not succeed"); } catch (error) { // Verify the wrapped error includes the original error message @@ -251,11 +246,10 @@ describe("runWithRetry Tests", () => { assert.strictEqual(causeMessage, "Throw error"); } // Initial call + maxRetries attempts - assert.strictEqual(retryTimes, maxRetries + 1, "Should retry exactly maxRetries times"); + assert.strictEqual(retryTimes, 4, "Should retry exactly maxRetries times"); }); it("Should succeed before maxRetries is exceeded", async () => { - const maxRetries = 5; let retryTimes = 0; const api = async (): Promise => { retryTimes += 1; @@ -270,9 +264,7 @@ describe("runWithRetry Tests", () => { }; const success = await runWithFastSetTimeout(async () => - runWithRetry(api, "test", logger, { - maxRetries, - }), + runWithRetry(api, "test", logger, {}, 5), ); assert.strictEqual(success, true, "Should succeed"); assert.strictEqual(retryTimes, 3, "Should take 3 attempts to succeed"); @@ -310,11 +302,7 @@ describe("runWithRetry Tests", () => { }; try { - await runWithFastSetTimeout(async () => - runWithRetry(api, "test", logger, { - maxRetries: 0, - }), - ); + await runWithFastSetTimeout(async () => runWithRetry(api, "test", logger, {}, 0)); assert.fail("Should not succeed"); } catch (error) { // Verify the wrapped error includes the original error message From e9ebaebf151e7d956621490d641d804b20d77b2c Mon Sep 17 00:00:00 2001 From: Kian Thompson Date: Mon, 23 Mar 2026 11:17:33 -0700 Subject: [PATCH 4/4] Change flag name to DisableCloseOnAttachFailure --- packages/common/container-definitions/src/loader.ts | 2 +- packages/loader/container-loader/src/container.ts | 12 +++++++----- .../loader/container-loader/src/test/loader.spec.ts | 4 ++-- .../test-end-to-end-tests/src/test/blobs.spec.ts | 2 +- .../src/test/detachedContainerTests.spec.ts | 2 +- .../src/test/serializeAfterFailedAttach.spec.ts | 2 +- 6 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/common/container-definitions/src/loader.ts b/packages/common/container-definitions/src/loader.ts index 01afd00bc98b..4af177e3a4ce 100644 --- a/packages/common/container-definitions/src/loader.ts +++ b/packages/common/container-definitions/src/loader.ts @@ -421,7 +421,7 @@ export interface IContainer extends IEventProvider { * * By default, the container will close if attach fails. * However, closure can now be avoided in most cased by setting: - * Fluid.Container.RetryOnAttachFailure to true + * Fluid.Container.DisableCloseOnAttachFailure to true * via the config provider passed to the loader. * * If attach fails, check the closed property to discover if retry is possible. diff --git a/packages/loader/container-loader/src/container.ts b/packages/loader/container-loader/src/container.ts index 21c4d3908003..fcda91121a38 100644 --- a/packages/loader/container-loader/src/container.ts +++ b/packages/loader/container-loader/src/container.ts @@ -1301,7 +1301,9 @@ export class Container }); // only enable the new behavior if the config is set - if (this.mc.config.getBoolean("Fluid.Container.RetryOnAttachFailure") !== true) { + if ( + this.mc.config.getBoolean("Fluid.Container.DisableCloseOnAttachFailure") !== true + ) { attachP = attachP.catch((error) => { throw normalizeErrorAndClose(error); }); @@ -1547,11 +1549,11 @@ export class Container service.on("metadataUpdate", this.metadataUpdateHandler); } } else { - // When RetryOnAttachFailure is enabled, use no internal retries + // When DisableCloseOnAttachFailure is enabled, use no internal retries // The consumer will own the retry policy - const retryOnAttachFailure = - this.mc.config.getBoolean("Fluid.Container.RetryOnAttachFailure") === true; - const maxRetries = retryOnAttachFailure ? 0 : undefined; + const disableCloseOnAttachFailure = + this.mc.config.getBoolean("Fluid.Container.DisableCloseOnAttachFailure") === true; + const maxRetries = disableCloseOnAttachFailure ? 0 : undefined; service = await runWithRetry( async () => diff --git a/packages/loader/container-loader/src/test/loader.spec.ts b/packages/loader/container-loader/src/test/loader.spec.ts index 3072a99416ba..cae59fc32d3b 100644 --- a/packages/loader/container-loader/src/test/loader.spec.ts +++ b/packages/loader/container-loader/src/test/loader.spec.ts @@ -98,7 +98,7 @@ describe("loader unit test", () => { urlResolver: failProxy(), configProvider: { getRawConfig: (name): ConfigTypes => - name === "Fluid.Container.RetryOnAttachFailure" ? true : undefined, + name === "Fluid.Container.DisableCloseOnAttachFailure" ? true : undefined, }, }); const detached = await loader.createDetachedContainer({ package: "none" }); @@ -136,7 +136,7 @@ describe("loader unit test", () => { }), configProvider: { getRawConfig: (name): ConfigTypes => - name === "Fluid.Container.RetryOnAttachFailure" ? true : undefined, + name === "Fluid.Container.DisableCloseOnAttachFailure" ? true : undefined, }, }); const detached = await loader.createDetachedContainer({ package: "none" }); diff --git a/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts b/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts index 724df0a58b23..fce8f07f43cd 100644 --- a/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/blobs.spec.ts @@ -583,7 +583,7 @@ function serializationTests({ loaderProps: { documentServiceFactory, configProvider: createTestConfigProvider({ - "Fluid.Container.RetryOnAttachFailure": true, + "Fluid.Container.DisableCloseOnAttachFailure": true, }), }, }); diff --git a/packages/test/test-end-to-end-tests/src/test/detachedContainerTests.spec.ts b/packages/test/test-end-to-end-tests/src/test/detachedContainerTests.spec.ts index c2625763be88..14a298fb1c30 100644 --- a/packages/test/test-end-to-end-tests/src/test/detachedContainerTests.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/detachedContainerTests.spec.ts @@ -956,7 +956,7 @@ describeCompat("Detached Container", "NoCompat", (getTestObjectProvider, apis) = { configProvider: { getRawConfig: (name) => - name === "Fluid.Container.RetryOnAttachFailure" ? true : undefined, + name === "Fluid.Container.DisableCloseOnAttachFailure" ? true : undefined, }, }, ); diff --git a/packages/test/test-end-to-end-tests/src/test/serializeAfterFailedAttach.spec.ts b/packages/test/test-end-to-end-tests/src/test/serializeAfterFailedAttach.spec.ts index 8c1610a5d267..9f000da9371f 100644 --- a/packages/test/test-end-to-end-tests/src/test/serializeAfterFailedAttach.spec.ts +++ b/packages/test/test-end-to-end-tests/src/test/serializeAfterFailedAttach.spec.ts @@ -87,7 +87,7 @@ describeCompat( logger: provider.logger, configProvider: { getRawConfig: (name) => - name === "Fluid.Container.RetryOnAttachFailure" ? true : undefined, + name === "Fluid.Container.DisableCloseOnAttachFailure" ? true : undefined, }, }); return testLoader;