Windowsで開発していると、こんな経験はないでしょうか。
- 昨日まで通っていた
next buildが、ローカルだけ突然panicで落ちる。CIやVercelでは緑のまま - エラーメッセージを検索しても同じ症例がほとんど出てこず、切り分けに半日溶ける
- タスクスケジューラに登録した定時バッチが、エラーも吐かずに「動いていないことに数日後気づく」
私はこの3つを、すべて同じ原因で踏みました。プロジェクトを「ドキュメント」「〇〇 作業」のような日本語(非ASCII)を含むパスの下に置いていたことです。
この記事で分かること:
- 日本語パスが原因で実際に壊れた3つの事例(Next.js 16 / Node 25 / タスクスケジューラ)と、その回避策
- 「ローカルだけ壊れてCI・クラウドは正常」という非対称性がなぜ厄介なのか
- 既に日本語パスで運用してしまっている場合の現実的な逃げ道
なお、いずれも筆者が執筆時点で実際に遭遇した事象です。バージョンや環境により再現しない場合があります。「必ず壊れる」ではなく「壊れることがあり、壊れたときの症状が分かりにくい」という話として読んでください。
地雷1: Next.js 16 の Turbopack が next build でpanicする
症状
Next.js 16 では Turbopack がビルドに使われますが、プロジェクトパスに日本語が含まれていると、ローカルの next build がpanicでクラッシュすることがあります。
# 日本語を含むパスの下で
PS C:\Users\yourname\日本語フォルダ\my-next-app> npx next build
# → Turbopack が panic でクラッシュすることがある
panicはアプリケーションコードのエラーではなくビルドツール内部の異常終了なので、スタックトレースを眺めても自分のコードのどこが悪いのかは分かりません。コードは1行も変えていないのに落ちる、というのが混乱ポイントです。
回避策
執筆時点で私が使っている回避策は2つです。
# 回避策1: Webpackビルドに切り替える
npx next build --webpack
# 回避策2: ビルドせず型チェックだけ行う
npx tsc --noEmit
--webpack でWebpackビルドに切り替えるとローカルでもビルドが通ります。「デプロイ前に型エラーだけ検知できればよい」場面なら、tsc --noEmit で型チェックのみ行うのも実用的です。
そして重要なのが、Vercel上のビルドでは問題が起きないという点です。Vercelのビルド環境はLinuxで、ビルドパスはASCIIだからです。つまり「ローカルで落ちる=デプロイできない」ではありません。慌ててNext.jsのバージョンを巻き戻す前に、パスを疑ってください。
地雷2: Node 25 の Windows で fs.cpSync がクラッシュする
症状
Node 25 の Windows 環境では、日本語パス配下で fs.cpSync がクラッシュすることがあります。
私が遭遇したのは Astro プロジェクトで、@astrojs/vercel アダプタを使ったローカルビルドの途中で落ちました。アダプタが内部でファイルコピーを行う際に fs.cpSync を通るためです。自分のコードで cpSync を直接呼んでいなくても、依存パッケージが内部で使っていれば踏みます。ここが厄介なところで、エラーの発生箇所が node_modules の奥深くになるため、原因がパスにあると気づくまで時間がかかりました。
回避策
これも Turbopack の件と同じく、CI や Vercel 上では問題が起きませんでした。そこで私は「ローカルでフルビルドを通す」こと自体を諦め、検証を次のように分担しました。
| 検証したいこと | ローカルでの代替手段 |
|---|---|
| 型・構文の妥当性 | astro check |
| ロジックの正しさ | ユニットテスト(vitest) |
| ビルドが通ること | CI / Vercel 側のビルドに任せる |
# ローカルではビルドの代わりにこの2つを回す
npx astro check
npx vitest run
「ローカルビルドが通らないと不安」という気持ちは分かりますが、原因が環境(パス×Nodeバージョン)にあると特定できているなら、検証の役割分担で切り抜けるのが現実的です。
地雷3: タスクスケジューラ × PowerShell 5.1 が「無言で」失敗する
症状
3つの中でこれが一番怖い地雷です。
Windows タスクスケジューラから PowerShell 5.1(powershell.exe)で、日本語パスにあるスクリプトを -File 指定で実行すると、エラーも出さずに無言で失敗することがあります。
# タスクスケジューラの「操作」設定(失敗する例)
プログラム: powershell.exe
引数: -File "C:\Users\yourname\日本語フォルダ\scripts\daily-job.ps1"
タスクスケジューラの履歴上はタスクが起動した記録が残るのに、スクリプトの中身は実行されていない。ログも例外も残らない。定時実行というのは「動いて当たり前」の前提で組むものなので、動いていないことに気づくのが数日後になり得ます。手動でスクリプトを直接実行すると普通に動くため、余計に原因へたどり着きにくいです。
回避策
PowerShell 7(pwsh.exe)を使うと動きました。
# タスクスケジューラの「操作」設定(動いた例)
プログラム: pwsh.exe
引数: -File "C:\Users\yourname\日本語フォルダ\scripts\daily-job.ps1"
PowerShell 7 は標準搭載ではないのでインストールが必要ですが、タスクスケジューラで日本語パスのスクリプトを回すなら、執筆時点では pwsh.exe を指定するのが安全側の選択だと考えています。
あわせて、定時タスクには「実行された証拠を残す」仕組み(スクリプト冒頭でのログファイル追記など)を入れておくと、この種の無言死をすぐ検知できます。
3つに共通する教訓 —「ローカルだけ壊れる」非対称性
3つの事例を並べると、共通パターンが見えてきます。
| 地雷 | ローカル(日本語パス) | CI / クラウド |
|---|---|---|
| Next.js 16 Turbopack |
next build がpanic |
Vercelでは正常 |
Node 25 fs.cpSync
|
ローカルビルドでクラッシュ | CI / Vercelでは正常 |
| タスクスケジューラ + PS 5.1 | 無言で失敗 | (そもそもローカル固有の問題) |
切り分けを難しくしているのは、この**「ローカルだけ壊れてCI・クラウドは正常」という非対称性**です。CIが緑だと「コードは正しい」と判断してしまい、ローカル環境側、それもフォルダ名という地味な要素を疑う優先順位はどうしても下がります。しかも症状が「panic」「クラッシュ」「無言の失敗」とバラバラなので、同一原因だと気づきにくい。
教訓としては次の3点です。
-
これから作るワークスペースは英数字パスに置くのが最も安全。
C:\dev\やC:\projects\のような浅いASCIIパスなら、この記事の問題はそもそも起きません -
既に日本語パスで運用中でも、詰みではない。
next build --webpack、tsc --noEmit/astro check/ vitest への検証の振り替え、pwsh.exeへの切り替えで、移行せずに切り抜けられます - 「ローカルだけ壊れた」ときは、コードより先にパスを疑う選択肢を持つ。特に非ASCII文字・スペースを含むパスは、ツールチェーンのテスト対象から漏れやすい領域です
まとめ
- Next.js 16 の Turbopack は、日本語を含むパスでローカルの
next buildがpanicすることがある。--webpackかtsc --noEmitで回避でき、Vercel上のビルドは影響を受けない - Node 25 の Windows では、日本語パス配下で
fs.cpSyncがクラッシュすることがある(筆者は @astrojs/vercel のローカルビルドで遭遇)。astro checkやユニットテストで検証を代替し、ビルドはCI / Vercelに任せる手がある - タスクスケジューラ + PowerShell 5.1 の
-Fileは、日本語パスのスクリプトで無言失敗することがある。pwsh.exe(PowerShell 7)なら動いた。定時タスクには実行ログを仕込んでおく - 共通の教訓: 新規ワークスペースは英数字パスへ。既存の日本語パス運用は上記の回避策で延命できる。「ローカルだけ壊れてCI / クラウドは正常」なら、パスを疑う
いずれも執筆時点・筆者環境での事象であり、バージョンや環境により再現しない場合があります。それでも「日本語フォルダ名は、壊れるときに静かに壊れる」という感覚を持っておくだけで、切り分けにかかる時間は大きく変わるはずです。同じ地雷を踏んだ誰かの検索に、この記事が引っかかれば幸いです。