Skip to content

os doctor 载入 objectstack.config.ts 时不带 .env* overlay —— 配置文件自己读 process.env 时,doctor 报「Could not load config」而 os serve 同目录正常启动 #5397

Description

@baozhoutao

发现于 #5387(doctor 对齐 serve 的 .env* 读取顺序)实施过程中的顺带核验;本单只记录,不在该 PR 里改 —— 原因写在下面。

事实

#5387 之后,doctor 会按 os serve 的顺序读 .env*,但读到的值只在需要它的那一次读取周围临时生效(withDotenvOverlay),刻意不合并进整轮运行的 process.env。今天套上 overlay 的只有 env 派生检查(posture)那一处;loadConfig() 没有套。

两条命令的顺序因此仍然不同:

  • serve:dotenvFlow.config()(packages/cli/src/commands/serve.ts:520)→ 之后才 bundleRequire 载入用户的 objectstack.config.ts。配置文件顶层读到的 process.env 含 .env* 的值。
  • doctor:readDotenvFiles()(不写 process.env)→ loadConfig()(packages/cli/src/commands/doctor.ts 的 config 分析块)。配置文件顶层读到的 process.env 不含 .env* 的值。

后果

配置文件在顶层读环境变量是常见写法(数据源 URL、开关)。当变量只写在 .env 里时:

  1. 值不同 —— 依赖该值的结构(条件声明的 object / datasource)在 doctor 与 serve 眼里不是同一份,doctor 的 config 检查判定的是一份服务器不会运行的配置;

  2. 更响的一种 —— 配置在缺值时抛错(throw new Error('OS_DATABASE_URL is required') 之类),doctor 会落进 config 分析那个很宽的 try,打印

    ⚠ Could not load config for analysis (config checks skipped)
    

    记一个 warning、exit 0,而 os serve 在同一个目录正常启动。这句话正是 os doctor 对非法 OS_TENANCY_POSTURE 退出码 0 并报告「环境功能正常」—— 抛错被 config 分析的宽 catch 吞成一句「Could not load config」 #5382 判定为「归因错误」的那一句:配置本身没问题,问题是 doctor 没把 .env 交给它。

为什么没有顺手改

给 loadConfig() 套上 overlay 会改变既有 config 检查(circular deps / unused objects / orphan views / dashboard integrity / spec 版本)的输入,可能新增或消除 warning —— 属于诊断输出的另一处契约变化,超出 #5387 派发时被限定的判定面(该单的口径明确要求:若改变既有检查的判定超出预期就停下报告)。

需要决定的是同一个问题的另一半:doctor 的 config 分析应当在哪一份环境下进行 —— serve 的那份(overlay 覆盖 loadConfig(),与运行时一致,但既有检查的判定面会变),还是当前这份(只覆盖显式声明的 env 输入,判定面不变,但 config 那条路径与 serve 仍不一致)。

现状

零件已经就位,不需要新机制:readDotenvFiles() / withDotenvOverlay() 就在同一个文件里(#5387 引入,packages/cli/src/commands/doctor.ts),把 loadConfig() 的调用包进去即可。packages/cli 下没有任何测试钉 doctor 的 config 载入与 .env 的关系。

Depends-on: #5387(其 PR 引入的两个零件是本单的前置)。与 #4801、cloud#1020 同属「诊断面与运行时不一致」家族。


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions