できない.dev

Next.js の Server Action が実行できない

Server Action は use server ディレクティブが付いた関数のみが対象で、Client Component から呼ぶ場合は別ファイル(先頭に use server)に書く必要がある。
form の action 属性に関数を直接渡し、App Router 環境で利用する。
Pages Router では使えない。

公開: 更新:

症状できない · exit 1
npx next build > build.log 2>&1
解決後できた · exit 0
npx next build > build.log 2>&1

2026-10-13 に node:20(Node.js 20.20.2 / npm 10.8.2) で実際に打って取った出力。検証環境の詳細

要約

Server Action が動かない場合、最初に疑うのは "use server" ディレクティブの位置と、Client Component 側からの呼び出し方法。
Client Component の中に inline で書いた async 関数はそのままでは Server Action にならないため、別ファイルに切り出して先頭で "use server" を宣言し、<form action={fn}> か useTransition 経由で呼ぶ。
App Router 専用機能で、Next.js 14 以降では既定で有効。

実行例

Client Component の中に "use server" の関数を inline で定義すると、Next.js 15.5.27 の next build は It is not allowed to define inline "use server" annotated Server Actions in Client Components を出して終了コード 1 で失敗した。
Server Action を別ファイルへ切り出してファイル先頭に "use server" を置くと、ビルドは終了コード 0 で通っている。next start で起動して JavaScript なしの送信と同じ形の multipart POST を curl で送ると、サーバー側で createTodo が実行されてログに送信した値が残った。

$ npx next build > build.log 2>&1
$ echo $?
1
$ grep -m1 -o "It is not allowed to define inline.*Client Components" build.log
It is not allowed to define inline "use server" annotated Server Actions in Client Components
$ npx next build > build.log 2>&1
$ echo $?
0
$ curl -s -o /dev/null -w '%{http_code}\n' -F '$ACTION_ID_40649793bfb4fc1bbe874c5b5462ac0afcfcf6b893=' -F title=buy-milk http://localhost:3000/
200
$ grep buy-milk start.log
buy-milk

— 2026-10-13 時点の出力

検証環境Node.js 20.20.2 / npm 10.8.2 / Python 3.11.2 / 2026-10-13 検証(ほか 2 件)
検証日
実行環境
node:20 Debian GNU/Linux 12 (bookworm)
バージョン
  • Node.js 20.20.2
  • npm 10.8.2
  • Python 3.11.2
  • Git 2.39.5
  • Next.js 15.5.27

この記事の「実行例」は、上記の環境で実際にコマンドを実行して得られた出力をそのまま掲載しています。 再現手順はリポジトリの検証スクリプトとして管理し、定期的に再実行して出力を更新しています。

解決策

1. アクションを別ファイルに切り出す

// app/actions.ts
"use server";
 
export async function createTodo(formData: FormData) {
  const title = formData.get("title");
  // ... DB 書き込み等
}
// app/page.tsx (Server Component)
import { createTodo } from "./actions";
 
export default function Page() {
  return (
    <form action={createTodo}>
      <input name="title" />
      <button type="submit">追加</button>
    </form>
  );
}

ファイル先頭の "use server" で、その module の全 export が Server Action として扱われる(公式ドキュメント(新しいタブで開く))。

2. Client Component から呼ぶ

"use client";
import { useTransition } from "react";
import { createTodo } from "./actions";
 
export function AddBtn() {
  const [pending, start] = useTransition();
  return (
    <button onClick={() => start(() => createTodo(new FormData()))} disabled={pending}>
      追加
    </button>
  );
}

3. App Router に移行する

pages/ を app/ に置き換えるのは段階的でよい。
並走させた上で、Server Action を使う画面だけ app/ で実装する。

4. Next.js を更新する

npm install next@latest

14 系以上に上げ、next.config.js に古い experimental.serverActions 設定が残っていれば削除する。
アップデート後は next dev を再起動する。

よくある原因

  1. Client Component("use client" 付き)の中に async function submit() { ... } を書いて onSubmit に渡しているが、これはただのクライアント側関数で Server Action ではない。
  2. button.onClick={fn} から Server Action を直接呼ぼうとしている。
    Server Action は <form action={fn}> か startTransition(() => fn()) 経由で起動するのが想定。
  3. プロジェクトが Pages Router(pages/ 配下)で運用されている。
    Server Action は App Router の機能で、Pages Router にはバックポートされていない。
  4. Next.js 13.4 以前で experimental.serverActions フラグを立てていない、または next dev を再起動していない。

この手順で直った?