Vercel Build Failed 怎么解决:先读 log 的这三个位置

Vercel 部署变红时别慌——build log 已经把真正的报错写出来了,关键是知道往哪看。三个 log 位置,加上最常见的 6 类失败和精确修复。

deployment 列表里那条红色的 Build Failed 本身不可怕,可怕的是滚动几千行 log 却找不到真正的报错。Vercel 的 build log 是按时间顺序混在一起的:install 阶段的 npm warning、TypeScript 的提示、framework 自己的进度条全堆在一块,真正的错误经常被一堆绿色 info 行盖住。

最快的修法: 打开失败的 deployment,点 Building 展开 log,直接跳到最底部。最后一段 stack trace 和那行 Error: command "..." exited with N 几乎每次都能点出真因。137 是内存不足,1 是 build 报错(类型错误、模块找不到、env var 缺失)。这篇先教你 30 秒扫完 log 里的三个关键位置,再把最常见的 6 类失败一一对应到精确修复。适用于 Next.js、Astro、Vite、Remix、SvelteKit 以及任何在 Vercel 上构建的框架。

先读 log 的三个位置

不管是哪类失败,先扫这三处:

  1. 最末尾的 stack trace——log 最底下那一段。Node 抛错时,报错信息后面的前两行就是真因。
  2. exit code 那一行——通常是倒数第二行 Error: command "..." exited with N。每个 N 的含义见下表。
  3. 高亮的 error——Vercel 会把 error:Error: 染红。用浏览器的 Find(Cmd/Ctrl+F)搜 error 在这些行之间跳,跳过噪音。
Exit code含义接着看哪
137内存不足(SIGKILL)下面的内存小节
1通用 build 报错最末尾的 stack trace——类型错误、模块缺失或 env var 缺失
2命令/shell 用法错package.json 里的 build 脚本
134进程被 abort(SIGABRT)native module 或断言失败

常见原因,按命中率排序

从高频到低频。

1. Node / 依赖版本本地和 Vercel 不一致

最高频。截至 2026 年 6 月,新建的 Vercel 项目默认用当前受支持的最新 Node LTS,也就是 24.x(22.x、20.x 也可选)。如果你本地还是 Node 20,而 Vercel 跑 24,那些有 native binding 的包(sharpcanvasbcryptbetter-sqlite3)就会 ABI 不兼容、编译失败。

gyp ERR! build error
node-pre-gyp ERR! Tried to download(404): https://...

如何判断: log 最顶部会显示 Running "install" commandDetected ... Node.js version,对照本地 node -v。差一个或更多 major 版本,基本就是这问题。

修复: 两边都把版本钉死。dashboard 里进 Settings → Build and Deployment → Node.js Version,下拉选成和本地一致的版本。然后在 package.json 里锁住,让仓库成为唯一事实来源:

{
  "engines": {
    "node": "22.x"
  }
}

engines.node 的 major 版本会覆盖 dashboard 下拉里的选项,所以一旦提交,每次 build 都可复现。

2. 生产 env var 缺失或拼写错

build 阶段需要的变量(NEXT_PUBLIC_SUPABASE_URLSANITY_PROJECT_ID)只加在了 Preview scope,没加 Production;或者在 dashboard 里写成了 SUPABSE_URL(拼错)。

Error: Environment variable NEXT_PUBLIC_SUPABASE_URL is not set
  at Object.<anonymous> (/vercel/path0/lib/supabase.ts:4:5)

如何判断: 在 log 里搜 is not setundefined,旁边跟着你认识的变量名。

修复:Settings → Environment Variables。添加变量时,All Environments 复选框默认是勾上的——保持勾上,值就同时应用到 Production、Preview、Development。如果每个 scope 需要不同的值,取消勾选,再为每个环境各加一遍。注意 NEXT_PUBLIC_*(以及类似带框架前缀的)变量是在 build 时内联进代码的,所以改了它必须重新部署,光重启没用。

3. OOM——build 超内存(exit 137)

每个 Vercel build 容器分配的内存是 8192 MB(8 GB),Hobby 和 Pro 都一样。大型 Next.js 项目、千页静态生成、或太重的 TypeScript 类型推断都可能撑爆它,然后 kernel 用 SIGKILL 把进程杀掉。

<--- Last few GCs --->
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
Error: command "npm run build" exited with 137

如何判断: log 末尾出现 exited with 137heap out of memory

修复: 抬高 Node 的堆上限。Vercel 官方建议用 --max-old-space-size=6144,而不是 8192——留出约 2 GB 余量,免得 Node 进程自己反倒成了被 OOM 杀掉的那个。写进 build 脚本:

{
  "scripts": {
    "build": "NODE_OPTIONS='--max-old-space-size=6144' next build"
  }
}

如果不想把它写进仓库,就在 Settings → Environment Variables 里加一条 NODE_OPTIONS = --max-old-space-size=6144。如果加完还是 OOM,真正的解法是降低内存压力(分页静态生成、关掉 production source map、用 experimental.webpackBuildWorker)——Pro/Enterprise 还可以开 Enhanced Builds,把容器升到 16 GB 内存、8 CPU、58 GB 磁盘

4. TypeScript strict / lint 错误本地被跳过

next buildastro build 会跑类型检查(Astro 是 tsc --noEmit;Next.js 在 build 时做类型检查),遇到第一个错误就失败。本地 npm run dev 跳过完整类型检查,所以开发时没暴露出来。

Type error: Property 'user' does not exist on type 'Session | null'.
  47 | export default function Page({ session }) {
  48 |   return <div>{session.user.name}</div>
                              ^

如何判断: log 里有 Type error:、形如 error TS2339 的字符串,或带具体文件行号的 ESLint 错误。

修复: 本地跑生产 build——用 npm run build,不是 npm run dev——把类型错误改掉再 push。用 next.config.js 里的 typescript.ignoreBuildErrors 把它压下去虽然能让 build 过,但 bug 就一起带上线了,所以优先把类型修对。

5. Monorepo 的 Root Directory 配错

仓库是 monorepo(pnpm workspace、Turborepo、Nx),但 Vercel 项目的 Root Directory 留空或指错了子目录。build 找不到对的 package.json,或装了错误的依赖。

Error: No Next.js version detected. Make sure your package.json has "next" in either "dependencies" or "devDependencies".

如何判断: 紧跟在 Cloning ... 之后,Running "install" 那一步显示的工作目录不是你 app 所在的文件夹。

修复:Settings → Build and Deployment → Root Directory → Edit,设成放着该 app package.json 的文件夹(比如 apps/web)。改完重新部署。

6. 文件大小写在 macOS vs Linux 不一致

macOS 默认大小写不敏感,所以 Header.tsxheader.tsx 指向同一个文件。Vercel 在 Linux 上构建,是严格区分大小写的。代码里 import './header' 但文件叫 Header.tsx,本地能过,Vercel 报 module not found。

Module not found: Can't resolve './header' in '/vercel/path0/components'

如何判断: 错误是 Can't resolve './xxx',但你确认本地文件存在——这种情况约 99% 是大小写不一致。

修复: 把 import 字符串改成和文件完全一致的大小写。由于 Git 在 macOS 上对文件名大小写跟踪得比较松,要通过 Git 改名让 Linux 看到变化:git mv Header.tsx header.tsx(或改 import),再提交。

最短修复路径

Step 1:本地复现 Vercel 的 build 环境

# 对齐 Vercel 的 Node 版本(用你 dashboard / engines.node 显示的版本)
nvm use 22

# 清掉缓存彻底重 build
rm -rf node_modules .next dist
npm ci            # 严格按 lockfile 安装,等价于 Vercel
npm run build     # 生产 build,不是 dev

大约 90% 的情况,这一步本地就能复现,而本地迭代是瞬时的。让复现可信的关键是 npm ci(不是 npm install)——它严格按 lockfile 安装,和 Vercel 完全一致。

Step 2:按 log 关键词对症下药

log 关键词真因修复
exited with 137 / heap out of memoryOOMNODE_OPTIONS=--max-old-space-size=6144,或开 Enhanced Builds
is not set / undefined + 变量名env var 缺失Environment Variables 里按正确 scope 添加
Type error: / error TS2339TS strict本地跑 npm run build 把类型改对
Can't resolve './...'大小写不一致把 import 改成文件的精确大小写
gyp ERR! / node-pre-gypnative module + Node ABIengines.node 钉成一致,或换无 native binding 的包
No Next.js version detectedmonorepo Root DirectorySettings → Build and Deployment → Root Directory

Step 3:UI 截断时用 CLI 拿完整 log

dashboard 的 log 查看器滚动慢,还会折叠区块。要 grep 的话 CLI 更快:

# 查看某次 deployment 的日志
vercel inspect <deployment-url> --logs

# 用 Vercel 同款 builder 在本地复现,verbose
vercel build --debug

Step 4:用 Redeploy 测试,而不是 push 新 commit

测试纯配置类的修复(env var、Node 版本、Root Directory)时,在 dashboard 用 Redeploy,而不是 push 新 commit。想强制干净构建,就在 Redeploy 弹窗里取消勾选 Use existing Build Cache。其他绕过缓存的办法:

  • CLI:vercel --force
  • env var:在项目上设 VERCEL_FORCE_NO_BUILD_CACHE = 1

(build cache 每个 key 上限 1 GB、保留一个月,所以有时缓存过期本身就是元凶。)一旦某次 redeploy 通过,把永久修复 commit 回仓库。

如何确认真的修好了

deployment 上的绿勾是必要条件,但不充分。三项都确认:

  1. deployment 状态显示 Ready,不是 Error
  2. build log 以 Build Completed 和成功上传结尾,没有你跳过的 error 行。
  3. 部署后的 URL 真的能渲染——build 过了仍可能因为某个运行时 env var 不对而是白屏。如果是白屏,看 静态站打开是白屏

预防建议

  • package.json 里钉死 engines.node,和 dashboard 的 Node.js Version 对齐。
  • nvm use + npm ci + npm run build 本地复现 CI——复现时绝不用 npm installnpm run dev
  • 新 env var 立刻加到正确的 scope(除非真的要分环境用不同值,否则保持 All Environments 勾上)。
  • 在 pre-push hook 里跑 npm run build(或 tsc --noEmit + eslint),让类型和 lint 错误在到 Vercel 之前就暴露。
  • 定期在 Linux container(Docker 或 GitHub Actions)里 build 一次,抓出 macOS 藏起来的大小写和 native module 问题。
  • 把文件命名约定写进 CONTRIBUTING.md:组件首字母大写,路由小写,import 严格匹配。

常见问题

Vercel 上的 exited with 137 是什么意思? 是内存不足被杀。build 进程超过了容器的 8192 MB,kernel 发了 SIGKILL。给 build 加 NODE_OPTIONS=--max-old-space-size=6144,如果还不够,就降低 build 的内存压力,或在 Pro/Enterprise 上开 Enhanced Builds(16 GB)。

为什么本地能 build,Vercel 就失败? 通常三个原因:Node 版本不同(截至 2026 年 6 月 Vercel 默认 Node 24.x)、macOS 忽略但 Linux 严格的文件大小写、或者本地有但 Production scope 里没设的 env var。用相同 Node 版本跑 npm ci && npm run build 复现就能暴露。

怎么改 Vercel 用的 Node 版本? dashboard:Settings → Build and Deployment → Node.js Version。或者在 package.json 里提交 "engines": { "node": "22.x" },它会覆盖 dashboard 设置,并纳入版本控制。

Redeploy 时修好了,但下次 git push 又失败,为什么? Redeploy 复用上一次 deployment 的设置和源码。如果你只在 dashboard 里改了东西(某个 env var、Node 版本)而没把对应改动 commit 进仓库,下次 push 就还是用旧源码构建。把 package.json / 配置的改动也提交上去。

怎么看完整 build log,而不是被截断的 dashboard 视图? 用 CLI 的 vercel inspect <deployment-url> --logs,或者打开 deployment、展开 Building 那一步,用浏览器 Find 在 error 行之间跳。

相关阅读

Vercel 官方参考见 Troubleshooting Build Errors 文档和 SIGKILL / Out of Memory 指南

标签: #Vercel #部署 / 托管 #构建报错 #排查