本地能跑不等于环境里能跑

本地能跑不等于环境里能跑

# 本地能跑不等于环境里能跑

结论

你反复踩的是同一个坑:「本地正常」被当成「环境正常」的证据。 但本地与环境跑的不是同一份东西 —— 不是同一段代码路径、不是同一套配置键、 不是同一份可变状态(库 / 缓存 / 凭据)。 判据一句话:把两侧的差异项列出来,差异项就是唯一需要验证的清单。

五处证据:每一处都是「两侧根本不是同一份」

出处本地这一侧环境那一侧分叉点
本地开发脚本可能连生产资源以为「只是本地开发」实际连的是生产 Redis / 库环境变量文件里写的就是生产值
本地测试要显式覆盖数据源.env.local(软链到主目录)远程 / 生产数据源数据源没被显式覆盖
兼容端点要防SDK注入非标准字段没配 *_BASE_URL → 走 SDK 内置原生 provider配了 relay → 走兼容层,被多塞一个字段 → 400少一个环境变量就换了整条调用路径
集成已合并不等于运行时已启用本地有一套 key → 能 trace容器 env 里一个都没有 → 静默 noop能力在缺配置时静默关闭
无入站流量的服务靠数据与配置隔离环境另一个目录 / 另一个 compose 项目连的仍是正式库隔离看的是「共享了什么可变状态」

旁证:agent 程序本机就能跑,却每次都只能部署到云端验证 —— 因为它不会自己读 .env.local,要显式喂给它(clean/2026-07-29.md @ 21:36)。

综合判断

  1. 差异的来源不是「环境更差」,而是「环境里少了一个隐式默认」。 本地常见的隐式默认: 没配 base URL 就 fallback 到 SDK 原生 provider、Next.js 自动读 .env.local、框架给的默认值。 这些默认在环境里往往不存在,或指向别处 —— 于是同一份代码在两侧走了两条路。

  2. 这类分叉全部静默。 本地 200、线上 400;本地有 trace、线上零数据;本地连本地库、 线上连生产库。没有一条错误信息指向「你测的不是这一份」。

  3. 可迁移的动作:任何「本地验证过了」之后,追问三句 —— 「环境侧少了哪个默认?」「两侧的 provider 路径是同一段代码吗?」「两侧共享了哪些可变状态?」 把差异项列成清单,逐项在环境里验证一次。

  4. 环境隔离的判据不是「部署在哪」,而是「共享了什么可变状态」。 一个进程只要连了正式库, 就算部署在另一个目录、另一个 compose 项目里,也等于没有独立环境。

与既有 synthesis 的关系

为什么这是 synthesis

单看每一页,都是某个项目里的一次环境事故(连了生产库、relay 400、线上零 trace)。 并排之后才看得出它们共享同一个失败形状:把「一侧能跑」当成了「两侧同构」。

相关