AI & Agent Dev Bug Sandbox logo
AI & Agent Dev Bug Sandbox
Back to Radar

No-JS Progressive Enhancement Fails When Server Action Is Bound Inside A Client Component

When a Server Action is bound with .bind() inside a Client Component and used as a form action, submitting the form with JavaScript disabled leaves the browser pending indefinitely. The server executes the action, but the returned state is never rendered. Binding the action in a Server Component and passing it as a prop works correctly.

highConfidence 78%Next.jsAffected V16.4.0-Canary.10

Origin Analysis

React/Next.js does not serialize client-side bound arguments into the progressive enhancement form payload. When .bind() is called inside a Client Component, the pre-bound arguments exist only on the client and are not embedded in the SSR HTML's hidden action fields. A no-JS form POST therefore lacks the complete action reference (including bound arguments), causing the server to execute the action without them or to produce an RSC payload that cannot complete the document navigation, leaving the request pending.
1. Clone https://github.com/nikhilsnayak/next-client-bind-repro 2. Run `bun install` and `bun dev` 3. Disable JavaScript in the browser 4. Navigate to http://localhost:3000 5. Click "Update client-bound user" 6. Observe that the server action completes but the form submission remains pending and the returned state is not displayed

Fixing Code Block

Edge Case Audit

This workaround requires the bound arguments to be available in the Server Component. If they depend on client-side runtime state, you must lift that state to the server (e.g., via URL params, cookies, or server context). Rollback: if the client-bound pattern is only used with JavaScript enabled, you may revert to binding inside the Client Component; however, the original no-JS bug will remain. For production, prefer server-side binding until the upstream fix is released.

Ecosystem Topology