vercel/next.js · error

Attempted to call {export_name}() from the server but {expor

Error message

Attempted to call {export_name}() from the server but {export_name} is on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.

What it means

Same client-reference proxy mechanism as error 45, but for a *named* export of a 'use client' module. The proxy generates `export const <name> = registerClientReference(function() { throw ... }, ...)` for each named export, so invoking a named client function (e.g. a client hook, handler, or util) from server code throws with the export name included. The message tells you exactly which export is on the wrong side of the boundary.

Source

Thrown at crates/next-core/src/next_client_reference/ecmascript_client_reference/ecmascript_client_reference_module.rs:120

                                function() {{ throw new Error({call_err}); }},
                                {server_module_path},
                                "default",
                            );
                        "#,
                        call_err = StringifyJs(&format!(
                            "Attempted to call the default export of {server_module_path} from \
                             the server, but it's on the client. It's not possible to invoke a \
                             client function from the server, it can only be rendered as a \
                             Component or passed to props of a Client Component."
                        )),
                        server_module_path = StringifyJs(server_module_path),
                    )?;
                } else {
                    writedoc!(
                        code,
                        r#"
                            export const {export_name} = registerClientReference(
                                function() {{ throw new Error({call_err}); }},
                                {server_module_path},
                                {export_name_str},
                            );
                        "#,
                        export_name = export_name,
                        call_err = StringifyJs(&format!(
                            "Attempted to call {export_name}() from the server but {export_name} \
                             is on the client. It's not possible to invoke a client function from \
                             the server, it can only be rendered as a Component or passed to \
                             props of a Client Component."
                        )),
                        server_module_path = StringifyJs(server_module_path),
                        export_name_str = StringifyJs(export_name),
                    )?;
                }
            }
        } else {
            is_esm = false;

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Stop calling the named export from server code; either render a client component that uses it internally, or move that function into a server-safe module.
  2. Split the file: keep 'use client' on the component file, and put pure shared logic in a separate server-safe module both can import.
  3. If it must be a client behavior, pass it down via props or use a Server Action for the reverse direction.
  4. Grep server files for `import { ... } from '<client module>'` and remove direct invocations.

Example fix

// before (server)
import { handleClick } from './client-utils' // 'use client'
handleClick(event) // throws: Attempted to call handleClick()...

// after — invoke inside a client component
// client-component.tsx ('use client')
import { handleClick } from './client-utils'
<button onClick={handleClick} />
Defensive patterns

Strategy: type-guard

Validate before calling

// Move shared logic into a server-safe module; import that from both sides.
// shared.ts (NO 'use client')
export function pureUtil(x: number) { return x + 1 }
// client.tsx ('use client') imports pureUtil for UI only
// server.tsx imports pureUtil directly — no boundary violation

Type guard

function isClientExportCall(serverSrc: string, clientPath: string): boolean {
  // crude: detect `import { x } from '<client>'` followed by `x(`
  return new RegExp(`from\\s+['"]${clientPath}['"][\\s\\S]*\\b\\w+\\(`).test(serverSrc)
}

Prevention

When it happens

Trigger: In server code, doing `import { useThing } from './client-mod'` (where client-mod has 'use client') and then calling `useThing()`. Or `import { handle } from './client'; handle(req)`. Any named export of a client module invoked as a function from the server triggers it.

Common situations: Calling a client hook (useState/useEffect wrapper) from a Server Component; invoking a client-side event handler imported from a 'use client' barrel; refactoring a util out of a client file and still importing it server-side.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/8f517896d201a2d9. Report an issue: GitHub.