nextjs - ✅(Solved) Fix Transition deadlock when navigating and double calling server action [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#84299Fetched 2026-04-08 02:19:59
View on GitHub
Comments
1
Participants
2
Timeline
25
Reactions
4
Author
Participants
Timeline (top)
referenced ×13subscribed ×6cross-referenced ×2labeled ×2

Fix Action

Fixed

PR fix notes

PR #89281: fix: resolve transition deadlock when navigating with pending server action

Description (problem / solution / changelog)

What?

This PR fixes a transition deadlock that occurs when a navigation action is dispatched while a server action is pending.

Why?

Fixes #84299

When a user triggers a navigation with a pending server action (e.g., clicking a button that calls router.push() followed by a server action inside startTransition), and then clicks again before the first action completes, the application enters a deadlock state where:

  • The navigation never completes
  • Subsequent button presses have no effect
  • The app becomes unresponsive

This was introduced in v15.2.2 (likely by #75362).

How?

The root cause was in the action queue logic in app-router-instance.ts. When a navigation action is dispatched while a server action is pending:

  1. The pending action is correctly marked as discarded
  2. However, the discarded action's promise was never resolved
  3. This left React's useTransition hanging indefinitely, causing the deadlock

The fix ensures that discarded actions still resolve their promises (using the current state) even if the result is discarded. This allows the React transition to complete successfully without applying the stale state update.

// Before: Promise never resolved for discarded actions
if (action.discarded) {
  runRemainingActions(actionQueue, setState)
  return  // ❌ BUG: Promise never resolved!
}

// After: Resolve promise with current state
if (action.discarded) {
  runRemainingActions(actionQueue, setState)
  action.resolve(actionQueue.state)  // ✅ FIX: Transition can complete
  return
}

Test Plan

Added e2e test that:

  1. Starts a transition with navigation + server action
  2. Clicks again while the first action is pending
  3. Verifies navigation completes without deadlock

The test reproduces the exact scenario from the issue report.

Changed files

  • packages/next/src/client/components/app-router-instance.ts (modified, +33/-4)
  • test/e2e/app-dir/action-queue-transition-deadlock/action-queue-transition-deadlock.test.ts (added, +73/-0)
  • test/e2e/app-dir/action-queue-transition-deadlock/app/actions.ts (added, +7/-0)
  • test/e2e/app-dir/action-queue-transition-deadlock/app/layout.tsx (added, +8/-0)
  • test/e2e/app-dir/action-queue-transition-deadlock/app/other/page.tsx (added, +8/-0)
  • test/e2e/app-dir/action-queue-transition-deadlock/app/page.tsx (added, +26/-0)
  • test/e2e/app-dir/action-queue-transition-deadlock/next.config.js (added, +6/-0)

Code Example

Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP PREEMPT_DYNAMIC Sun Aug  6 20:05:33 UTC 2023
  Available memory (MB): 4102
  Available CPU cores: 2
Binaries:
  Node: 20.9.0
  npm: 9.8.1
  Yarn: 1.22.19
  pnpm: 8.10.2
Relevant Packages:
  next: 15.6.0-canary.5 // There is a newer canary version (15.6.0-canary.32) available, please upgrade! 
  eslint-config-next: N/A
  react: 19.1.1
  react-dom: 19.1.1
  typescript: 5.3.3
Next.js Config:
  output: N/A
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://codesandbox.io/p/devbox/next-js-transition-starvation-kpl45h

To Reproduce

  1. Start the application in development or production.
  2. Open the network tab in the browser devtools.
  3. Click the button on the home page. This will start a transition which pushes a new path and then awaits a server action.
  4. Once the server action has started pending and has not completed yet, click the button again.
<img width="1276" height="317" alt="Image" src="https://github.com/user-attachments/assets/e207aa60-d196-4619-9ebe-be4667f90137" />

Current vs. Expected behavior

Current Behavior:

  • The navigation never completes and the second action is dropped (not visible in the network tab).
  • Subsequent presses to the button also do not navigate, indicating the application is in a transition deadlock.

https://github.com/user-attachments/assets/d06388c6-14af-44f7-99ff-a195709013d3

Expected behavior:

  • Both actions should fire from the home page, and once both complete, the navigation should occur.

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #1 SMP PREEMPT_DYNAMIC Sun Aug  6 20:05:33 UTC 2023
  Available memory (MB): 4102
  Available CPU cores: 2
Binaries:
  Node: 20.9.0
  npm: 9.8.1
  Yarn: 1.22.19
  pnpm: 8.10.2
Relevant Packages:
  next: 15.6.0-canary.5 // There is a newer canary version (15.6.0-canary.32) available, please upgrade! 
  eslint-config-next: N/A
  react: 19.1.1
  react-dom: 19.1.1
  typescript: 5.3.3
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Server Actions

Which stage(s) are affected? (Select all that apply)

next dev (local), next start (local)

Additional context

I tested various older versions of Next.js, and I believe this was introduced in v15.2.2. I suspect PR #75362 is related to the issue.

<sub>NEXT-4733</sub>

extent analysis

TL;DR

Upgrading to a newer version of Next.js, such as 15.6.0-canary.32, may resolve the transition deadlock issue when navigating and double-calling server actions.

Guidance

  • Verify the issue is reproducible with the provided steps and environment.
  • Check the network tab in the browser devtools to confirm the second action is dropped and not visible.
  • Consider upgrading to the latest canary version of Next.js, as the issue may have been introduced in v15.2.2 and potentially fixed in a later version.
  • Review PR #75362 to understand the potential changes related to the issue.
  • Test the application with the upgraded Next.js version to confirm the fix.

Notes

The provided information suggests a potential issue with Next.js version 15.2.2 and later. However, without further details or confirmation from the Next.js team, it's uncertain whether upgrading will fully resolve the issue.

Recommendation

Apply workaround: Upgrade to the latest canary version of Next.js (15.6.0-canary.32) to potentially resolve the transition deadlock issue, as the current version (15.6.0-canary.5) may contain the bug introduced in v15.2.2.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING