Commit 6cf6ae33444 for woocommerce

commit 6cf6ae33444463b0bacde771430362da7df1c444
Author: Anand Rajaram <anandrajaram21@gmail.com>
Date:   Mon Aug 31 18:31:17 2026 -0700

    Fix Mini-Cart mutations aborted during navigation (#68165)

    * Enable keepalive for batched mutations

    * Add changefile(s) from automation for the following project(s): woocommerce

    * Limit keepalive to supported mutation payload sizes

    ---------

    Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
    Co-authored-by: Tung Du <dinhtungdu@gmail.com>

diff --git a/plugins/woocommerce/changelog/68165-65956-mini-cart b/plugins/woocommerce/changelog/68165-65956-mini-cart
new file mode 100644
index 00000000000..76fcfcd1267
--- /dev/null
+++ b/plugins/woocommerce/changelog/68165-65956-mini-cart
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Prevent Mini-Cart item removals from being cancelled when navigating away.
diff --git a/plugins/woocommerce/client/blocks/assets/js/base/stores/woocommerce/mutation-batcher.ts b/plugins/woocommerce/client/blocks/assets/js/base/stores/woocommerce/mutation-batcher.ts
index 5195ee0a8c3..36ab31f8bcc 100644
--- a/plugins/woocommerce/client/blocks/assets/js/base/stores/woocommerce/mutation-batcher.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/base/stores/woocommerce/mutation-batcher.ts
@@ -79,6 +79,8 @@ type TrackedRequest< TMeta = unknown > = {
 	reject: ( error: Error ) => void;
 };

+const KEEPALIVE_PAYLOAD_LIMIT = 64 * 1024;
+
 export function createMutationQueue< TState, TMeta = unknown >(
 	config: MutationQueueConfig< TState, TMeta >
 ) {
@@ -256,14 +258,18 @@ export function createMutationQueue< TState, TMeta = unknown >(
 					};
 				} )
 				.filter( Boolean );
+			const body = JSON.stringify( { requests } );

 			const response = await fetchHandler( endpoint, {
 				method: 'POST',
+				keepalive:
+					new TextEncoder().encode( body ).byteLength <
+					KEEPALIVE_PAYLOAD_LIMIT,
 				headers: {
 					'Content-Type': 'application/json',
 					...requestHeaders,
 				},
-				body: JSON.stringify( { requests } ),
+				body,
 			} );

 			if ( ! response.ok ) {
diff --git a/plugins/woocommerce/client/blocks/assets/js/base/stores/woocommerce/test/mutation-batcher.test.ts b/plugins/woocommerce/client/blocks/assets/js/base/stores/woocommerce/test/mutation-batcher.test.ts
index a7c3efbc10e..01b78f713a1 100644
--- a/plugins/woocommerce/client/blocks/assets/js/base/stores/woocommerce/test/mutation-batcher.test.ts
+++ b/plugins/woocommerce/client/blocks/assets/js/base/stores/woocommerce/test/mutation-batcher.test.ts
@@ -103,6 +103,7 @@ describe( 'createMutationQueue', () => {

 			// Should have made exactly ONE fetch call with all 3 requests
 			expect( mockFetch ).toHaveBeenCalledTimes( 1 );
+			expect( mockFetch.mock.calls[ 0 ][ 1 ].keepalive ).toBe( true );
 			const requestBody = JSON.parse(
 				mockFetch.mock.calls[ 0 ][ 1 ].body
 			);
@@ -112,6 +113,28 @@ describe( 'createMutationQueue', () => {
 			).toEqual( [ '/a', '/b', '/c' ] );
 		} );

+		it( 'disables keepalive for oversized payloads', async () => {
+			const mockFetch = createMockFetch( [
+				{ status: 200, body: { value: 10 } },
+			] );
+			global.fetch = mockFetch;
+
+			const queue = createMutationQueue( {
+				endpoint: '/batch',
+				getHeaders: () => ( {} ),
+				...stateHandler,
+			} );
+
+			await queue.submit( {
+				path: '/a',
+				method: 'POST',
+				body: { description: '🚀'.repeat( 17_000 ) },
+			} );
+
+			expect( mockFetch ).toHaveBeenCalledTimes( 1 );
+			expect( mockFetch.mock.calls[ 0 ][ 1 ].keepalive ).toBe( false );
+		} );
+
 		it( 'takes snapshot once at start of cycle, not per request', async () => {
 			const mockFetch = createMockFetch( [
 				{ status: 200, body: { value: 100 } },