vercel / vercel/next.js

Inline `"use server"` function fails when returned from file-level `"use server"` function

Open
#96,508 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Server Actions
Dominant language
JavaScript
Stars
142k
Forks
32.4k
Avg merge
2d 14h
Merged PRs (30d)
351

Description

Link to the code that reproduces this issue

https://github.com/hi-ogawa/reproductions/tree/main/next-rsc-returned-nested-action

To Reproduce

The reproduction exercises the natural composition of the two "use server" forms. An exported function inherits the file-level directive and returns a nested function with its own inline directive and one closure capture.

'use server'

export async function outer(prefix: string) {
  async function inner(value: string) {
    'use server'
    return `${prefix}:${value}`
  }

  return inner
}

The routes differ only in how the Client Component receives outer:

  1. /imported imports outer directly into the Client Component.
  2. /prop imports outer in the Server Component and passes it to the Client Component as a prop.

In both routes:

  1. Select Get inner. The client calls outer('captured'), stores its return value in a ref, and displays stored:function.
  2. Select Call inner. The client calls the retained function with 'client'.

The issue is that /prop case succeeds but /imported case fails with a following error:

 POST /imported 200 in 8ms (next.js: 1.6ms, application-code: 7ms)
  └─ ƒ outer("captured") in 0ms app/imported/actions.ts
Error: Failed to find Server Action "609f86498f34d90b3fc12f77914ba6f5f15698574f". This request might be from an older or newer deployment.
Read more: https://nextjs.org/docs/messages/failed-to-find-server-action

Run the automated reproduction with:

pnpm install
pnpm test
Current vs. Expected behavior

On /imported, outer succeeds and returns a function to the client, but invoking that returned function fails:

UnrecognizedActionError: Server Action "<inner-action-id>" was not found on the server.

On /prop, the same sequence succeeds and produces:

result:captured:client

I expected /imported to produce the same result. The returned value is serialized to the client as a Server Action reference, so its generated action ID should remain resolvable when the client invokes it.

Provide environment information
Operating System:
  Platform: darwin
  Arch: arm64
Binaries:
  Node: 24.18.1
  pnpm: 10.34.5
Relevant Packages:
  next: 16.3.0-canary.106
  react: 19.2.4
  react-dom: 19.2.4
  typescript: 5.9.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 build (local), next start (local)

Additional context

The split result was verified in:

  • Turbopack development.
  • Webpack development.
  • Turbopack production followed by next start.

PR #62052 added support for nested inline actions inside module-level "use server" files. Its example includes an exported action returning nested actions, but its coverage is at the SWC transform layer. The transform works in this reproduction; the missing piece is publication of the generated nested export for the direct Client Component import path.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the reproduction's app/imported/actions.ts and compare the direct Client Component import path with /prop; run pnpm install and pnpm test to observe the failing nested action call. Done means /imported resolves the returned inner action and produces result:captured:client, matching /prop, across the reproduction's tested modes.

Written by the indexing model from the issue text.

Assessment

Tech stack
next.js, react, typescript
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.