Anchor部署Solana程序至devnet失败 提示账户非可升级或已被占用
问题描述
本地环境执行anchor deploy部署程序运行正常,切换集群到devnet后,使用anchor build生成的程序地址修改了Anchor.toml与lib.rs配置文件,尝试两种方式部署均失败:
- 执行
anchor deploy --provider.cluster devnet直接通过Anchor部署 - 先执行
solana config set --url https://api.devnet.solana.com切换Solana集群配置,再执行solana program deploy /target/deploy/voter.so通过原生Solana命令部署
两种方式返回的报错信息一致:
Deploying workspace: https://api.devnet.solana.com Upgrade authority: /home/XXXXXX/.config/solana/id.json Deploying program "voter"... Program path: /home/<user>/workspace/voter/target/deploy/voter.so... Error: Account xxxx is not an upgradeable program or already in use There was a problem deploying: Output { status: ExitStatus(unix_wait_status(256)), stdout: "", stderr: "" }.
报错原因
报错核心是你要部署的目标程序ID(即报错信息里的xxxx账户)在devnet链上已经被占用,且该账户不是标准可升级程序账户格式,无法直接覆盖或升级部署。
常见触发场景:
- 之前在devnet部署同个程序时操作中断,残留了格式异常的程序账户
- 本地生成的程序密钥对应的地址刚好和devnet上其他用户已部署的程序地址碰撞(概率极低但存在)
- 修改
Anchor.toml和lib.rs里的程序ID后没有重新编译,链上目标地址和本地编译出的.so文件绑定的地址不匹配
解决方案
按操作优先级依次尝试即可:
- 方案一:生成全新程序密钥对(成功率最高,优先试)
- 删除项目目录下
target/deploy/路径里旧的voter-keypair.json文件 - 执行
anchor keys sync,命令会自动生成新的程序密钥对,同时同步替换Anchor.toml和lib.rs里的旧程序ID - 执行
anchor build全量重新编译,确保生成的voter.so和新程序ID完全匹配 - 给新生成的程序地址申领devnet测试SOL作为部署手续费:
solana airdrop 2 <新生成的程序地址> --url devnet - 重新执行
anchor deploy --provider.cluster devnet完成部署
- 删除项目目录下
- 方案二:保留原有程序ID,清理链上残留账户
- 确认当前本地使用的钱包是该程序ID对应账户的升级权限持有方
- 执行
solana program close <程序ID> --url devnet --bypass-warning,关闭链上残留的异常程序账户,释放地址占用 - 重新执行部署命令即可
注意:每次修改lib.rs中declare_id!字段或Anchor.toml里的程序地址配置后,必须重新执行anchor build编译,否则编译出的程序字节码和目标部署地址不匹配,会反复触发同类报错。
内容的提问来源于stack exchange,提问作者Satyaban Sahoo
相关产品推荐
相关产品推荐

