Vercel Hobby 下 vercel --prod Unexpected error

Vercel Hobby 计划下使用 vercel --prod 部署出现 Unexpected error 的真实原因分析:并非 CLI 或网络问题,而是 Git commit author 与 Vercel team 权限校验冲突(多 GitHub / SSH / Vercel 账号场景)。附完整排查与解决方案。

VercelVercel Hobbyvercel --prodVercel Unexpected errorVercel Deployment BlockedVercel commit authorVercel Git author 校验Vercel 多账号GitHub 多账号 SSHgit user.emailgit commit authorSSH config 多账号Vercel CLI 部署失败Vercel team 权限Hobby plan 限制

现象

Hobby计划下,使用 vercel 命令行部署时候出现: Error: Unexpected error. Please try again later. ()

vercel --prod
 
🔍  Inspect: https://vercel.com/xx-projects/xx-site/xx [4s]
  Preview: https://xx-site-xx-projects.vercel.app [4s]
Error: Unexpected error. Please try again later. ()

输出debug信息, vercel --prod --debug,出现类似错误:

[client-debug] 2026-03-16T06:25:05.466Z Waiting for builds and the deployment to complete...
> [debug] [2026-03-16T06:25:05.666Z] #4 ← 200 OK: sfo1::9z6ng-1773642305713-c49af82dc718 [201ms]
> [debug] [2026-03-16T06:25:05.815Z] #5 → GET https://api.vercel.com/v3/now/deployments/xxx
[client-debug] 2026-03-16T06:25:06.111Z Yielding a 'error' event
> [debug] [2026-03-16T06:25:06.113Z] Retrying: AbortError: The user aborted a request.
AbortError: The user aborted a request.
    at abort2 (file:///xx/pnpm/global/5/.pnpm/vercel@50.32.5_typescript@5.9.3/node_modules/vercel/dist/chunks/chunk-QXRJ52T4.js:2796:23)
    at AbortSignal.abortAndFinalize2 (file:///xx/pnpm/global/5/.pnpm/vercel@50.32.5_typescript@5.9.3/node_modules/vercel/dist/chunks/chunk-QXRJ52T4.js:2810:11)
    at [nodejs.internal.kHybridDispatch] (node:internal/event_target:843:20)
    at AbortSignal.dispatchEvent (node:internal/event_target:776:26)
    at runAbort (node:internal/abort_controller:488:10)
    at abortSignal (node:internal/abort_controller:459:3)
    at AbortController.abort (node:internal/abort_controller:507:5)
    at stopSpinner (file:///xx/pnpm/global/5/.pnpm/vercel@50.32.5_typescript@5.9.3/node_modules/vercel/dist/chunks/chunk-4S3Y3ATR.js:4321:22)
    at processDeployment (file:///xx/pnpm/global/5/.pnpm/vercel@50.32.5_typescript@5.9.3/node_modules/vercel/dist/chunks/chunk-4S3Y3ATR.js:4474:9)
    at process.processTicksAndRejections (node:internal/process/task_queues:104:5)
> [debug] [2026-03-16T06:25:06.115Z] Error: Error

CLI 的报错是“假象”,真正的错误在 Vercel 控制台。

进入:

👉 https://vercel.comDeployments

出现状态为 Blocked 的记录,进入详情页面提示:

### Deployment Blocked

Git author xxx@users.noreply.github.com must have access to the team xxx's projects on Vercel to create deployments.

---

Hobby teams do not support collaboration. Please upgrade to Pro to add team members.

Learn More          Upgrade to Pro

原因

不是 CLI 问题,也不是网络问题,而是部署身份校验失败。

曾经可能操作过:

  1. 注册两个或以上的 Vercel Hobby 计划账号;
  2. 两个Vercel的项目使用一个 GitHub 账号维护;
  3. Vercel Hobby 计划对绑定 GitHub 有限制,只能绑定一个;
  4. 于是:
    1. 第一个使用GitHub集成部署;
    2. 第二个使用Vercel CLI命令行部署,规避账号绑定数量的限制;
    3. 之前是可以使用的,但是最近的规则调整了;
  5. 使用一个GitHub账号提交,默认使用-global的配置;
  6. commit log中的 author 信息只对应第一个 Vercel Hobby计划;
  7. 第二个在提交的时候,触发了限制。

问题本质:身份体系冲突

本地机器  
│  
├─ Git  
│ ├─ user.name  
│ └─ user.email      <- 决定 commit author
│  
├─ SSH  
│ ├─ private key  
│ ├─ public key      <- 决定 Github 身份
│ └─ ~/.ssh/config  
│  
├─ GitHub  
│ ├─ 账号A  
│ └─ 账号B  
│  
└─ Vercel  
├─ 账号A / Team A  
└─ 账号B / Team B
└─ 部署权限校验

本质:Git、SSH、GitHub、Vercel 这四套身份体系交叉了。

Git / SSH / Vercel 各自负责什么

  • SSH key 解决的是:你是谁,能不能连接 GitHub
  • git user.name / user.email 解决的是:这次 commit 是谁提交的
git log -1
 
# 输出
 
commit d2d24af5187906626f81ae382305848b7b7e8e63
Author: your-name <xxx@users.noreply.github.com>
Date: Mon Mar 16 17:43:04 2026 +0800
  • GitHub 账号 解决的是:仓库归谁、SSH key 属于谁
  • Vercel,决定谁可以部署,commit author 是否属于当前 team

Vercel 校验逻辑

Hobby 计划下,Vercel 可能会尝试确认:

  1. 当前部署的项目属于哪个账号 / team;
  2. 当前 Git commit 的作者是谁;
  3. 这个 commit author 是否有权限在该 team 下部署。

如果发现:

  • commit author 不属于这个 team;
  • 或者看起来像“另一个用户提交的代码”;

则会认定为“协作场景”。

Hobby 计划不支持这类私有仓库协作,于是部署会被直接 Blocked

所以这个问题不是:

  • SSH 连不上;
  • Vercel CLI 坏了;
  • GitHub push 失败;

而是:

部署身份校验失败。

💡 简单说:Vercel CLI 会读取当前 Git 仓库信息,会检查:

git log -1
 
# 输出
commit d2d24af5187906626f81ae382305848b7b7e8e63 (HEAD -> main, origin/main)
Author: [vercel_account] <xxx@users.noreply.github.com>
Date:   Mon Mar 16 17:43:04 2026 +0800

然后把这个 author 作为部署身份校验的一部分。

如果:

  • 这个邮箱不是 Vercel account 的邮箱
  • 或者这个邮箱属于另一个 GitHub 用户
  • 或者这个邮箱不是 team owner

会直接拒绝部署:

  • 认为是团队协作,相当于多个用户;
  • Hobby 计划不支持团队协作;
  • 如果需要多个用户部署,需要升级到 Pro。

Vercel 文档 Team configuration 说明了详细的限制。

Hobby teams The Hobby Plan does not support collaboration for private repositories. If you need collaboration, upgrade to the Pro Plan.

[Hobby 方案] 不支持私有仓库的团队协作。如果您需要协作功能,请升级至 [Pro 方案]

To deploy commits under a Hobby team, the commit author must be the owner of the Hobby team containing the Vercel project connected to the Git repository. This is verified by comparing the Login Connections Hobby team's owner with the commit author.

若要在 Hobby 团队下部署提交(commit),提交者(commit author)必须是包含该 Vercel 项目的 Hobby 团队的所有者。系统会通过对比 Hobby 团队所有者的 [登录连接 (Login Connections)] 与提交者信息来验证身份。

To make sure we can verify your commits:

为了确保我们能成功验证您的提交,请执行以下操作:

  1. Make sure all commits are authored by the git user associated with your account. 确保所有提交的作者信息(git user)都与您的账号相关联。
  1. Link your git provider to your Vercel account in Account Settings[账号设置 (Account Settings)] 中将您的 Git 服务商(如 GitHub/GitLab)连接至 Vercel 账号。

If your account is not connected to your git provider, make sure you've properly configured your Vercel email address so that it matches the email associated with the commit.

如果您的账号尚未连接 Git 服务商,请务必正确配置您的 [Vercel 邮箱地址],使其与提交记录中的邮箱保持一致。

For the most reliable experience, ensure both your project and account are properly connected to your git provider.

为了获得最稳定的体验,请确保您的项目和账号都已与 Git 服务商正确连接。

临时解决方案(修改 Git author)

  1. 进入仓库,确认 commit author
git log -1
  1. 先看当前 Git 配置:
git config user.email
  1. 改为正确账号
git config user.name "你的名字"
git config user.email "你的vercel邮箱" 

最好使用仓库级:

git config --local user.name "你的名字"  
git config --local user.email "你的邮箱"
  1. 修正最近一次提交
git commit --amend --reset-author
  1. 重新 push 和部署
git push --force-with-lease
 
vercel --prod

根本解决方案(多账号隔离)

真实环境:

Mac  
├─ GitHub 账号 A  
│ └─ SSH key A  
│  
├─ GitHub 账号 B  
│ └─ SSH key B  
│  
├─ SSH config  
│ ├─ github.com → 账号A  
│ └─ github-b → 账号B  
│  
└─ Vercel  
├─ Account A  
└─ Account B
  • 同一台开发机器;
  • 两个或多个 GitHub 账号;
  • 两个或多个 SSH key;
  • 两个或多个 Vercel 账号;
  • 使用 SSH 连接 GitHub;
  • 使用 Vercel CLI 进行部署;

隔离原则

目标:建立一套账号隔离规则,以项目为边界作为隔离,保持账号之间的纯洁度,确保不同项目之间不会混淆身份,避免类似的错误发生;

  • 每个项目固定归属一个 GitHub 账号;
  • 每个项目固定归属一个 Vercel 账号 / scope;
  • 每个项目固定使用该账号对应的:
    • git user.name
    • git user.email
    • SSH key
  • 尽量不要让同一个项目中途换归属;真要换,就一次性迁移干净;
  • 主账号仓库,只用主账号自己的 email / 主账号自己的 noreply
  • 副账号仓库,只用副账号自己的 email / 副账号自己的 noreply
  • 不要混用两个账号的 noreply
  • SSH alias 必须和 remote 完全一致

配置

一台机器有多个 GitHub / Vercel 账号,不建议频繁修改--global

使用:

  • 全局保留主账号默认值;
  • 特殊项目在仓库内部使用 --local 单独配置

步骤

为不同的 GitHub 账号分别生成私钥和公钥;

GitHub Docs

  1. 打开终端,生成新的 SSH key
ssh-keygen -t ed25519 -C "your_email@example.com"
  1. 确认选项:
    • 输入名称时,不要覆盖原有的私钥和公钥匙:
    • 可以保留 passphrase 密码短语 为空;
> Generating public/private ALGORITHM key pair.
 
> Enter a file in which to save the key (/Users/YOU/.ssh/id_ALGORITHM): [Press enter]
 
> Enter passphrase (empty for no passphrase): [Type a passphrase]
 
> Enter same passphrase again: [Type passphrase again]

将新生成的 私钥和公钥,重命名,自己可以区分就行:

  • id_ed25519_b
  • id_ed25519_b.pub
  1. 将公钥上传至 GitHub

配置 ~/.ssh/config 为主账号和备用账号配置路由规则;

打开 ~/.ssh/config 文件,修改配置如下:

Host github.com
    # github 主账号
    AddKeysToAgent yes
    UseKeychain yes
    IdentityFile ~/.ssh/id_ed25519_main
    IdentitiesOnly yes

host github-b
    # github 备账号
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_b
    IdentitiesOnly yes

调整仓库信息

此处记录的是将原有的项目迁移到新的GitHub账号

  1. 新账号下创建私有仓库;
  2. 将原有项目拷贝到新仓库预备的目录;

初始化仓库

git init

给这个仓库单独配置 B 账号的身份

git config user.name "B账号的GitHub名称"  
git config user.email "B账号的noreply邮箱"

确认配置是否生效

git config --local --get user.name  
git config --local --get user.email
  1. 添加远程仓库

现在 SSH 的别名是github-b,不要使用默认的 github.com

git remote add origin git@github-b:[account]/[repo_name].git

检查

git remote -v

提交首个版本

git add .  
git commit -m "Initial commit"

把默认分支设为 main

git branch -M main

首次推送

git push -u origin main

验证发布

vercel --prod

SSH 基础知识

当执行:

git clone git@github.com:someone/repo.git
# 或者
git push

Git 借助 SSH 去连接 GitHub,本机会做以下几件事:

  1. 要连接的是哪个主机,比如 github.com
  2. ~/.ssh/config,看看这个主机该用什么规则
  3. 决定拿哪把私钥去尝试认证
  4. GitHub 收到公钥指纹后,判断是不是它认识的那个账号
  5. 如果对应得上,就允许 clone / push

所以:

  • 私钥在本地
  • 公钥上传到 GitHub
  • config 决定“访问某个主机时优先用哪把钥匙”

SSH相关文件基本是在目录:~/.ssh,可能包含的文件列表如下:

文件说明
configSSH 客户端的路由和规则表
id_ed25519私钥文件,非常重要,不能泄漏
id_ed25519.pub公钥文件,用于上传至 GitHub
known_hosts以前连过哪些 SSH 服务器,以及它们的主机指纹是什么
authorized_keys服务端使用

~/.ssh/config

最需要理解的:

  • 是:SSH 客户端“按主机匹配规则的配置文件”;
  • 核心作用不是“存密钥”;
  • 是告诉 SSH:连接某个目标时,该用哪套连接参数;
  • 类似“别名路由表”;

决定了:

  • 连哪个主机
  • 用哪个用户名
  • 用哪把私钥
  • 是否加到 agent
  • 是否使用 macOS keychain
  • 是否启用某些连接选项

核心参数:

参数说明
Host定义一个规则块。比如:Host github.com当 ssh 连接 github.com使用该规则块的配置
HostName主机的别名。比如:Host github-a HostName github.comgithub-a 实际连接 github.com
UserSSH 登录用户名,不同的服务器不同
服务SSH User
GitHubgit
GitLabgit
AWS EC2ec2-user
Ubuntuubuntu
所以,User git 意思是:ssh git@github.com
IdentityOnlyyes 只使用 config 指定的 key不尝试其他的 key
IdentityFile对应的私钥
AddKeysToAgent当 SSH 使用这把 key 时,自动加入 ssh-agent参见 ssh-agent
UseKeychainmacOS 把 SSH 密钥的 passphrase 存进 Keychain

比如:

Host *  
	ServerAliveInterval 60  
  
Host github.com  
	AddKeysToAgent yes  
	UseKeychain yes  
	IdentityFile ~/.ssh/id_ed25519_a
	
Host github-b  
	HostName github.com  
	User git  
	IdentityFile ~/.ssh/id_ed25519_b  
	IdentitiesOnly yes
  • Host github.com 和 Host github-b 本地自定义的别名
  • 最终都指向 github.com;
  • 但会分别使用不同的私钥;

于是:

git clone git@github.com:账号A/repo.git

会走账户 A 的key

git clone git@github-b:账号B/repo.git

会走账号 B 的 key。

这就是 config 最强大的地方,也是账户隔离的基础。

Host *

表示“所有 SSH 主机都套用这个规则,每 60 秒发一个保活包,减少连接空闲断开。

Host github.com

表示当你连接 github.com 时,用下面这些规则:

  • AddKeysToAgent yes
    这把 key 可以自动加入 ssh-agent,避免为此输入:

  • UseKeychain yes
    macOS 可把私钥口令记到钥匙串里

  • IdentityFile ~/.ssh/id_ed25519
    连接 GitHub 时,优先使用这把私钥,对应的公钥需要上传到 GitHub,在进行 SSH 连接时的验证。

ssh-agent

如果没有 ssh-agent,SSH 的工作流程是这样的:

  1. 执行
git push
  1. SSH 连接 github.com
  2. SSH 需要使用私钥
  3. 如果私钥有密码(passphrase),系统会问你:
Enter passphrase for key ~/.ssh/id_ed25519
  1. 输入密码后,SSH 才能使用这把私钥。

ssh-agent 是一个 本地后台进程,作用是: 缓存已经解锁的私钥,流程变成:

  1. 第一次输入私钥密码
  2. ssh-agent 记住这个私钥
  3. 以后 SSH 连接时直接向 agent 要签名
  4. 不再要求输入密码

所以:

ssh-agent = 本地私钥缓存代理

~/.ssh/id_ed25519 和 ~/.ssh/id_ed25519.pub

生成的私钥和公钥匙

~/.ssh/authorized_keys

作用:

  • 当别人 SSH 登录到这台机器时
  • 系统会检查 ~/.ssh/authorized_keys
  • 里面列出来的公钥,才允许登录

也就是说,它更像是:

“哪些公钥被允许登录这台机器”

所以在本机上,这个文件往往用于:

  • 远程登录到你的 Mac
  • 某些内部系统 / 跳板机 / git 服务
  • 某些容器或自动化工具写进去的允许登录公钥

~/.ssh/known_hosts

  • 防止“中间人攻击”
  • 核心安全设计之一

第一次连接服务器:

ssh root@xx

SSH 会收到服务器的 host public key

系统会提示:

The authenticity of host 'github.com' can't be established.  
RSA key fingerprint is SHA256:xxxxx.  
Are you sure you want to continue connecting (yes/no)?

如果输入:

yes

SSH 就会把这个指纹写入:

~/.ssh/known_hosts

例如:

github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...

第二次链接:

SSH 会做一个检查:

  1. 服务器给出的 host key
  2. known_hosts 里记录的
  3. 是否一致

如果一致:连接继续,否则:

WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

意味着:

  • 服务器可能被替换
  • DNS 被劫持
  • 网络中间人攻击

SSH 会直接拒绝连接。

假设攻击者做了:

你 → 攻击者服务器 → GitHub

攻击者试图伪装成 GitHub。

但攻击者的 host key 不可能和 GitHub 一样。

所以:

SSH 会发现:

known_hosts 的 key ≠ 当前服务器 key

然后拒绝连接。

这就是 SSH 的 TOFU 模型

Trust On First Use  
首次连接信任  
之后验证一致性

Git 配置与 author 机制

  1. Git 配置分层;
  2. 如何查看当前生效的是哪一层;
  3. git author 和 SSH 身份不是一回事;

Git config

Git 配置主要决定两类事情:

  1. Git 的行为习惯
    例如默认分支名、编辑器、换行符等;
  2. 提交身份
    例如:
    • user.name
    • user.email

例如:

git config user.name  
git config user.email

它们决定了 Git commit 里的作者信息。

查看最近一次提交:

git log -1
 
# 输出类似:
 
commit d2d24af5187906626f81ae382305848b7b7e8e63  
Author: your-name <xxx@users.noreply.github.com>  
Date:   Mon Mar 16 17:43:04 2026 +0800

这里的 Author,是 Vercel 会拿来校验的关键信息之一。

Git 配置通常有三层:

层级命令作用范围
systemgit config --system整台系统
globalgit config --global当前用户
localgit config --local当前仓库

通常最常用的是:

  • --global
  • --local

其中:

  • --global:当前用户所有仓库默认使用;
  • --local:只对当前项目生效,优先级高于 global。

查看某个值:

git config user.name
git config user.email

查看全局配置:

git config --global --list

查看当前仓库配置:

git config --local --list

查看所有配置以及来源:

git config --list --show-origin

这个命令非常有用,可以看到某个配置到底来自:

  • ~/.gitconfig
  • 当前仓库 .git/config
  • 还是系统配置文件

命令速查表

1. Git:查看当前作者信息

git config user.name  
git config user.email

作用:查看当前仓库实际生效的 Git 作者信息。

2. Git:查看全局配置

git config --global --list

作用:查看当前用户级别的 Git 配置。

3. Git:查看当前仓库配置

git config --local --list

作用:查看当前仓库自己的配置。

4. Git:查看配置来源

git config --list --show-origin

作用:查看某个配置到底来自哪里。

5. Git:查看最近一次提交作者

git log -1

作用:

  • 查看最近一次 commit 的作者信息;
  • Vercel 部署校验时会参考这里的 author。

6. Git:设置当前仓库作者信息

git config --local user.name "你的名字"  
git config --local user.email "你的邮箱"

作用:

  • 只修改当前仓库的作者身份,不影响其他项目。

7. Git:修正最近一次提交作者

git commit --amend --reset-author

作用:用当前 Git 配置重写最近一次 commit 的作者信息。

8. Git:查看远程仓库地址

git remote -v

作用:

  • 查看 fetch / push 使用的远程地址;
  • 排查 SSH alias 是否写对。

9. Git:修改远程仓库地址

git remote set-url origin git@github-b:account/repo.git

作用: 修改当前仓库 remote。

10. SSH:查看本地密钥文件

ls -la ~/.ssh

作用:查看 SSH 相关文件是否存在。

11. SSH:查看 agent 中已加载的 key

ssh-add -l

作用:查看 ssh-agent 当前缓存了哪些私钥。

12. SSH:测试 GitHub SSH 连接

ssh -T git@github.com  
ssh -T git@github-b

作用:测试当前 Host alias 是否能正确认证到对应 GitHub 账号。

13. SSH:查看详细连接过程

ssh -vT git@github-b

作用:查看 SSH 实际命中了哪条配置、尝试了哪把 key。

14. Vercel:查看当前登录账号

vercel whoami

作用:确认当前 CLI 登录的是哪个 Vercel 账号。

15. Vercel:查看调试日志

vercel --prod --debug

作用:

  • 查看 CLI 输出的调试信息;
  • 但最终还是要结合控制台 Deployments 页面判断真实错误。

暂无目录