🤖 由 issue-agent 自主提出,未经人工确认
现象
registry.json 里没有 default(或它是 null)时跑 lc code:
File "/usr/lib/python3.12/subprocess.py", line 1885, in _execute_child
self.pid = _fork_exec(
TypeError: expected str, bytes or os.PathLike object, not NoneType
bin/lc 的 cmd_code():
profile = reg.get("default")
sys.exit(subprocess.call(["codex", "--profile", profile] + list(argv), env=codex_env()))
None 一路传进 subprocess.call,在 fork 那一层炸掉。
本地复现(4 步,不需要 docker / 网络 / 真模型):造一个有 upstream 但没有 default 键的 registry.json,跑 lc sync,起一个对 /health 回 200 的假网关让 gw_alive 通过,然后 lc code。
为什么是问题
这正是 #12 第三梯队修过的那个形态——只是当时修的是 test / e2e。_targets() 的 docstring 写得很清楚:
没有默认上游时 reg.get("default") 是 None,原来会一路传进 subprocess,以 TypeError: expected str ... not NoneType 的 traceback 收场。
_targets() 现在被 cmd_test 和 cmd_e2e 调用,cmd_code 没有走这条路,于是同一个 bug 在 lc code 上原样留着。test-lc-commands.sh 里有 ✅ lc e2e 没有 TypeError 这条断言,但 code 没有对应的一条。
后果不严重(不泄密、不误连),但踩到的人恰好是最不该被 traceback 招待的那个:刚 lc rm 掉当前默认上游、或手工编辑过 registry.json 的新手。项目在别处对这类分支的要求一直是「给一句人话,不是 Python 栈」。
顺带,lc rm 删掉默认上游之后是否会重新指定 default,值得一并核一下——那可能就是走到这个状态最常见的路径。
建议怎么做
cmd_code 里在 gw_alive 检查之后加:
profile = reg.get("default")
if not profile:
die("没有默认上游,用 `lc use <name>` 选一个。可用: %s" % ", ".join(sorted(reg.get("upstreams") or {})))
上游表为空时应当指向 lc init 而不是 lc use,和 _targets() 的措辞对齐;能否直接复用 _targets() 需要看一下——它返回的是列表,而 code 只要一个,可能包一层更干净。
完成标准:test-lc-commands.sh 的 [6] 里加两条(假网关和假 codex 桩都已经就位):
- 无
default 时 lc code 非零退出、输出里没有 Traceback、并指向 lc use
- 此时压根没启动 Codex(
[6a] 已经有这个形态的断言可以照抄)
取舍
这条我看不出真正的取舍——就是一个漏网的输入校验,和 #12 第三梯队已经接受过的修法完全一致。唯一要定的是措辞(指向 lc use 还是 lc init),而这个照抄 _targets() 即可。
如果你觉得不值得单开一个 issue,直接关掉就是;我提出来是因为它有明确的完成标准和现成的门禁位置,不属于「代码可以更优雅」那一类。
来源
修 #42 时读 cmd_code 发现的。那个 PR 只动环境变量注入,没有夹带这个修复。
现象
registry.json里没有default(或它是null)时跑lc code:bin/lc的cmd_code():None一路传进subprocess.call,在 fork 那一层炸掉。本地复现(4 步,不需要 docker / 网络 / 真模型):造一个有 upstream 但没有
default键的registry.json,跑lc sync,起一个对/health回 200 的假网关让gw_alive通过,然后lc code。为什么是问题
这正是 #12 第三梯队修过的那个形态——只是当时修的是
test/e2e。_targets()的 docstring 写得很清楚:_targets()现在被cmd_test和cmd_e2e调用,cmd_code没有走这条路,于是同一个 bug 在lc code上原样留着。test-lc-commands.sh里有✅ lc e2e 没有 TypeError这条断言,但code没有对应的一条。后果不严重(不泄密、不误连),但踩到的人恰好是最不该被 traceback 招待的那个:刚
lc rm掉当前默认上游、或手工编辑过registry.json的新手。项目在别处对这类分支的要求一直是「给一句人话,不是 Python 栈」。顺带,
lc rm删掉默认上游之后是否会重新指定 default,值得一并核一下——那可能就是走到这个状态最常见的路径。建议怎么做
cmd_code里在gw_alive检查之后加:上游表为空时应当指向
lc init而不是lc use,和_targets()的措辞对齐;能否直接复用_targets()需要看一下——它返回的是列表,而code只要一个,可能包一层更干净。完成标准:
test-lc-commands.sh的[6]里加两条(假网关和假 codex 桩都已经就位):default时lc code非零退出、输出里没有Traceback、并指向lc use[6a]已经有这个形态的断言可以照抄)取舍
这条我看不出真正的取舍——就是一个漏网的输入校验,和 #12 第三梯队已经接受过的修法完全一致。唯一要定的是措辞(指向
lc use还是lc init),而这个照抄_targets()即可。如果你觉得不值得单开一个 issue,直接关掉就是;我提出来是因为它有明确的完成标准和现成的门禁位置,不属于「代码可以更优雅」那一类。
来源
修 #42 时读
cmd_code发现的。那个 PR 只动环境变量注入,没有夹带这个修复。