Skip to content

sessions: v0.1.1291 quits at start with "panic: close of nil channel" in refresh's publish #2932

Open

Description

@TimWongUp

What happens

After updating to v0.1.1291 (macOS arm64, Darwin 25.5), magpie quits every time a few seconds after start. It reproduces on every launch. Going back to v0.1.1290 fixes it: that build has been running normally on the same data.

Run from a terminal, the binary exits with status 2:

panic: close of nil channel

goroutine 103 [running]:
github.com/yetone/magpie/internal/sessions.refresh.func5(...)
	github.com/yetone/magpie/internal/sessions/sessions.go:886
github.com/yetone/magpie/internal/sessions.refresh(...)
	github.com/yetone/magpie/internal/sessions/sessions.go:900 +0xe08
github.com/yetone/magpie/internal/sessions.statsIn(0x0, ...)
	github.com/yetone/magpie/internal/sessions/stats.go:143 +0x430
github.com/yetone/magpie/internal/sessions.StatsAndNative(0x0)
	github.com/yetone/magpie/internal/sessions/stats.go:117 +0x68
github.com/yetone/magpie/internal/gui.combinedSessionStats(0x0)
	github.com/yetone/magpie/internal/gui/sessions.go:466 +0x48
github.com/yetone/magpie/internal/gui.statsFor(...)
	github.com/yetone/magpie/internal/gui/sessions.go:443 +0x2ac
github.com/yetone/magpie/internal/gui.warmSessions.func1.1.warmSteps.1()
	github.com/yetone/magpie/internal/gui/sessions.go:507 +0x20
github.com/yetone/magpie/internal/gui.warmUp(...)
	github.com/yetone/magpie/internal/gui/sessions.go:529 +0x38
github.com/yetone/magpie/internal/gui.warmSessions.func1.1()
	github.com/yetone/magpie/internal/gui/sessions.go:497 +0x50
github.com/yetone/magpie/internal/sessions.Warm(...)
	github.com/yetone/magpie/internal/sessions/quiet.go:31 +0x94
github.com/yetone/magpie/internal/gui.warmSessions.func1()
	github.com/yetone/magpie/internal/gui/sessions.go:497 +0x30
created by github.com/yetone/magpie/internal/gui.warmSessions in goroutine 1
	github.com/yetone/magpie/internal/gui/sessions.go:493 +0x50

Where it seems to come from

The panic is close(parsing[j.f.path]) in refresh's publish (sessions.go:886 at v0.1.1291). The parsing map arrived with c381e4c ("a read is never held by another read's refresh…", #2776), which is in 1291 and not in 1290.

For parsing[path] to be nil at publish time, its entry has to be deleted already. As far as I can see, only publish deletes entries. So probably the same path is published twice: either it is in todo twice in one refresh (the parsing[f.path] != nil check runs before any entry is set, so a duplicate in want gets past it and its channel is overwritten), or another refresh published it in between. I could not tell which file triggers it. A rough re-implementation of the listings for the agents on this machine found no duplicate paths, but that was not the real allFiles(). Agents with sessions here: Claude Code, Codex (incl. .jsonl.zst in archived_sessions), Grok, WorkBuddy, CodeBuddy Code, Pi, Cursor (agent-transcripts only), dsh, and Hermes (root state.db plus one named profile).

A guard against a duplicate path in todo (or publish skipping a nil channel) would at least keep the warm-up from taking the whole app down.

Activity

  1. JoeyWu-tech commented on Oct 19, 2026

    @JoeyWu-tech
    Contributor

    我在看这个。去重的兜底先做上,同时在找重复的 path 是哪个列表给的,有结果了发上来。

  2. JoeyWu-tech commented on Oct 19, 2026

    @JoeyWu-tech
    Contributor

    跟你猜的一样,是一次 refresh 里同一个 path 出现了两次。refresh 挑要读的文件时会先查 parsing[f.path],但这个条目要到后面建 job 时才设,所以重复的 path 两次检查都能过,变成两个 job 共用一个条目。第一个 publish 把它 close 掉并删了,第二个再 close 拿到的就是 nil,也就是你贴的 886 那行。

    改法是挑文件的时候就把条目设上,第二次出现的就会被挡住。加了个测试,在 main 上跑出来就是你这个 panic(886 / 900),改完通过。

    分支:https://github.com/JoeyWu-tech/magpie/tree/fix/2932-refresh-dup
    (两个 commit,fbd99cb 和 b4e9e20,base ab7ec8c,patch sha256 19933ae3f1bbb2633100196dd80758b62b13c205f1105971498eb4678c751740,用的是 git format-patch --stdout ab7ec8c..b4e9e20 | sha256sum)

    不过到底是哪个列表给了重复的 path,我没找到,每个 agent 自己的列表都按 path 去重了。我能想到的是两个 agent 的目录指到了同一个地方,比如 PI_CODING_AGENT_DIR 设成了 ~/.omp/agent,或者 CODEBUDDY_CONFIG_DIR 和 WORKBUDDY_CONFIG_DIR 是同一个目录。你那边有设过类似的变量吗?

    另外顺手修了个小的:sessions 包开 -race 跑的话,TestManageReadsOnlyTheAgentsItShows 在 main 上就是红的,测试里数解析次数用的是普通 int。CI 的 race 不跑这个包,所以一直没暴露。我单独放在 fbd99cb,排在主修复前面,不需要的话跳过它就行。

    全量测试和其他检查的结果都写在 commit 里了。

  3. TimWongUp commented on Oct 19, 2026

    @TimWongUp
    Author

    有,就是你猜的第二种。我的 ~/.zshrc 里有一行:

    export CODEBUDDY_CONFIG_DIR="$HOME/.workbuddy"

    所以 CodeBuddyDir() 和 WorkBuddyDir() 都是 ~/.workbuddy,codebuddyFiles() 和 workbuddyFiles() 会把 ~/.workbuddy/projects 下同一批 .jsonl 各列一遍(一个算 codebuddy:,一个算 workbuddy:)。allFiles() 直接拼起来,所以 want 里同一个 path 有两条。其他目录变量都没设,~/.omp 也不存在。

    谢谢这么快就修了。这样的话,除了 refresh 里的兜底,可能还要看一下:两个 buddy 共用一个目录的时候,会话会不会在列表和统计里各算一遍。

  4. JoeyWu-tech commented on Oct 19, 2026

    @JoeyWu-tech
    Contributor

    谢谢确认,这下对上了。你说的重复计算也是真的,我拿测试数据按你这行配置跑了一下:会话页上 WorkBuddy 的 3 个会话又以 CodeBuddy 的名义多列了一遍,用量那边则把这些调用全算到了 CodeBuddy 头上,两个页面连 agent 都对不上。

    在同一个分支上加了一个 commit 3b9b094:CodeBuddy 的目录如果就是 WorkBuddy 的目录(软链接也算),就只按 WorkBuddy 读一遍,会话页、用量、统计都一样,"会话从哪些目录读取"那里也只显示一次。

    有个取舍要说一下:从文件本身看不出是哪个工具写的,所以这个目录下的会话都算 WorkBuddy 的。用 CodeBuddy CLI 在里面开的会话,也会显示成 WorkBuddy、按 WorkBuddy 的方式恢复。目录本来是 WorkBuddy 的,那个变量只是把 CLI 挪过去了,所以我选了这边。如果你更希望反过来,告诉我一声。

    现在三个 commit 的 patch sha256 是 1bbff1f7a30ed094e1b1d53eeaa2a4dd4acb46c25f00700a430a824a03e90319(git format-patch --stdout ab7ec8c..3b9b094 | sha256sum),测试记录照旧写在 commit 里。

  5. TimWongUp commented on Oct 19, 2026

    @TimWongUp
    Author

    按 WorkBuddy 算就行,我这边没问题。

    那个变量是我当初为了让 CodeBuddy CLI 跟 WorkBuddy 共用一套配置加的,目录本来就是 WorkBuddy 的,归到它名下说得通。CLI 开的会话显示成 WorkBuddy、按 WorkBuddy 的方式恢复,我这边能接受。

    等合进 main 发了新版我就升上去,跑一下再回来说一声。谢谢,修得挺快的。

  6. nativeas commented on Oct 19, 2026

    @nativeas

    我这边在 v0.1.1292 仍然遇到了相同的启动退出问题,补充一份复现信息。

    环境

    • Magpie:0.1.1292(已安装的 macOS app)
    • macOS:27.0.1(26A434)
    • 架构:arm64 / Apple Silicon

    复现与实际表现

    1. 启动 /Applications/magpie.app。
    2. 应用启动后很快消失。
    3. 直接从终端运行 /Applications/magpie.app/Contents/MacOS/magpie,也复现了退出,退出码为 2,捕获到下面的 panic。

    预期是应用启动后保持运行。

    崩溃日志

    panic: close of nil channel
    
    goroutine 11 [running]:
    github.com/yetone/magpie/internal/sessions.refresh.func5(...)
        github.com/yetone/magpie/internal/sessions/sessions.go:886
    github.com/yetone/magpie/internal/sessions.refresh(...)
        github.com/yetone/magpie/internal/sessions/sessions.go:900 +0xe08
    github.com/yetone/magpie/internal/sessions.statsIn(...)
        github.com/yetone/magpie/internal/sessions/stats.go:143 +0x430
    github.com/yetone/magpie/internal/sessions.StatsAndNative(0x0)
        github.com/yetone/magpie/internal/sessions/stats.go:117 +0x68
    github.com/yetone/magpie/internal/gui.combinedSessionStats(0x0)
        github.com/yetone/magpie/internal/gui/sessions.go:466 +0x48
    github.com/yetone/magpie/internal/gui.statsFor(...)
        github.com/yetone/magpie/internal/gui/sessions.go:443 +0x2ac
    github.com/yetone/magpie/internal/gui.warmSessions.func1.1.warmSteps.1()
        github.com/yetone/magpie/internal/gui/sessions.go:507 +0x20
    github.com/yetone/magpie/internal/gui.warmUp(...)
        github.com/yetone/magpie/internal/gui/sessions.go:529 +0x38
    github.com/yetone/magpie/internal/gui.warmSessions.func1.1()
        github.com/yetone/magpie/internal/gui/sessions.go:497 +0x50
    github.com/yetone/magpie/internal/sessions.Warm(...)
        github.com/yetone/magpie/internal/sessions/quiet.go:31 +0x94
    github.com/yetone/magpie/internal/gui.warmSessions.func1()
        github.com/yetone/magpie/internal/gui/sessions.go:497 +0x30
    created by github.com/yetone/magpie/internal/gui.warmSessions in goroutine 1
        github.com/yetone/magpie/internal/gui/sessions.go:493 +0x50
    

    上面省略了调用参数中的内存地址。panic 之前还有一条 Gemini 登录失效提示:

    gemini: Gemini CLI is signed out (the sign-in was refused (400): Bad Request); run gemini and sign in again
    

    目前没有确认这条提示与 panic 有关,也尚未验证本机是否存在上文提到的重复会话目录配置。尚未回退版本或测试补丁。

  7. JoeyWu-tech commented on Oct 19, 2026

    @JoeyWu-tech
    Contributor

    @nativeas 1292 里还没有这个修复,补丁在我上面贴的分支上,等合进 main。

    方便的话帮忙看一下 ~/.zshrc(或者你用的 shell 配置)里有没有设 CODEBUDDY_CONFIG_DIR、WORKBUDDY_CONFIG_DIR 这类变量,指到同一个目录:

    grep -nE 'CODEBUDDY_CONFIG_DIR|WORKBUDDY_CONFIG_DIR|PI_CODING_AGENT_DIR' ~/.zshrc ~/.zprofile ~/.bashrc 2>/dev/null

    如果有,先把那行注释掉再启动就能绕过去。如果什么都没有,说明还有别的地方会把同一个文件列两次,我再接着查。补丁里的兜底两种情况都能挡住,只是想确认原因有没有找全。

    Gemini 那条应该没关系:崩的是启动时统计会话那一步,它不读 Gemini 的文件,那条只是 Gemini 账号登录过期的提示。

  8. nativeas commented on Oct 19, 2026

    @nativeas

    @JoeyWu-tech 谢谢说明。我这边检查了:

    • ~/.zshrc 和 ~/.zprofile 中,没有找到 CODEBUDDY_CONFIG_DIR、WORKBUDDY_CONFIG_DIR、PI_CODING_AGENT_DIR 或 OMP_CODING_AGENT_DIR 的设置。
    • ~/.zshenv、~/.bashrc 和 ~/.bash_profile 不存在。
    • 用于排查的终端进程环境中,上述四个变量也都未设置。不过还没有核对 Finder / LaunchServices 启动应用时的环境,也没有全面检查这些配置文件间接加载的其他脚本。

    所以目前没有找到你提到的共用目录变量,尚不能确认本机是通过哪种路径触发了重复读取。暂时没有修改 shell 配置,也没有测试分支补丁。

    我会等包含修复的官方 macOS 版本发布后再更新验证。如果还需要检查特定目录、软链接或其他信息,麻烦告诉我具体检查项,我再补充结果。谢谢!

  9. JoeyWu-tech commented on Oct 19, 2026

    @JoeyWu-tech
    Contributor

    谢谢帮忙查,那应该是别的变量,我上次列得太少了。能挪会话目录的变量其实有十几个,而且桌面版的环境是从登录 shell 借来的,所以用登录 shell 查一遍最准,间接加载的脚本也会算进去:

    zsh -lic env 2>/dev/null | grep -E '^(CLAUDE_CONFIG_DIR|CODEX_HOME|CODEX_SQLITE_HOME|QODER_CONFIG_DIR|QODERCN_CONFIG_DIR|CODEBUDDY_CONFIG_DIR|WORKBUDDY_CONFIG_DIR|PI_CODING_AGENT_DIR|PI_CODING_AGENT_SESSION_DIR|GROK_HOME|KIMI_CODE_HOME|DSH_HOME|FACTORY_HOME_OVERRIDE|CURSOR_CONFIG_DIR|CURSOR_DATA_DIR|HERMES_HOME|CLINE_DIR|CLINE_DATA_DIR|CLINE_SESSION_DATA_DIR|OPENCODE_DB|XDG_DATA_HOME)='
    grep -n sessionDir ~/.pi/agent/settings.json 2>/dev/null

    第二条是 Pi 的会话目录设置,它也能把别的 agent 的文件夹算进来。输出里只有路径,没有密钥。

    要是两条都什么也没打出来,麻烦说一下你装了哪些 agent,我照着目录再排查。

  10. nativeas commented on Oct 19, 2026

    @nativeas

    @JoeyWu-tech 按你补充的方法又检查了一遍:

    1. 在 zsh -lic 登录交互式 shell 中运行 env,筛选你列出的全部目录变量,没有任何匹配输出。
    2. ~/.pi/agent/settings.json 不存在,所以该文件里也没有可检查的 sessionDir 设置。

    另外补充 agent 信息:在同样的登录 shell 中,通过 command -v 确认可找到的 CLI 有 Claude Code、Codex、Gemini CLI、Hermes。

    也检查了 pi、omp、qoder、codebuddy、workbuddy、grok、kimi、dsh、droid、cursor-agent、cline 和 opencode,这些命令在该 shell 的 PATH 中都没有找到。这只是 PATH 检查结果,尚不能排除其他安装位置或旧的会话目录残留。

    目前仍未修改目录配置或测试分支补丁。如果需要进一步核对默认目录、软链接或残留会话文件,请告诉我具体检查项,我再补充。谢谢!

  11. JoeyWu-tech commented on Oct 19, 2026

    @JoeyWu-tech
    Contributor

    @nativeas 辛苦了,查得很细。这样看你机器上确实没设什么变量。你装的这几个 agent 我又对着代码过了一遍,Claude Code、Codex、Hermes 列文件时都会先去重,暂时没找到能把同一个文件列两次的地方,这个只能先留着。

    不过不影响修复:分支上的改动是 refresh 拿到一个文件就先占上,同一个路径不管从哪儿多冒出来一次都只读一遍,所以不管来源是什么都不会再崩。

    等新版出来你升上去以后,如果看到会话页里同一个会话出现两次,或者用量像是翻了倍,在这儿说一声就行,我再按那个会话倒着查。

  12. tianhao2316-beep commented on Oct 20, 2026

    @tianhao2316-beep

    补充一个 Windows 上的同类复现,崩溃栈与本 issue 一致。

    环境与复现

    • Windows 25H2,OS build 26200.9711,x64。
    • 出问题的 Magpie 版本:0.1.1293(桌面 GUI)。
    • 2026-10-20 实际启动程序并捕获 stdout/stderr:启动数秒后自行退出,退出码 2。
    • 无需手动打开会话页面;崩溃发生在启动后的 warmSessions -> StatsAndNative -> refresh 调用链。
    • stderr 在 panic 之前显示两次 [WebView2] Environment created successfully。

    回退验证

    备份后,保留现有账户、模型配置和原始会话文件,将程序替换为官方 0.1.1290,并设置 noAutoUpdate=true 防止自动升级回去。下载文件已与官方 SHA256SUMS 核对一致。

    回退后已实际打开会话页面,成功加载 751 个 Codex 会话;截至本次检查已连续运行约 7 分钟,窗口正常响应,启动日志未再出现 panic。

    目前尚未确认本机是哪份会话文件/目录被重复枚举,未测试本 issue 中的修复分支,也未在本机测试 0.1.1294。因此这里只补充 0.1.1293 的 Windows 复现与 0.1.1290 的回退结果。

    崩溃日志

    以下省略了调用参数中的内存地址,函数名和源码行号保留:

    panic: close of nil channel
    
    goroutine 114 [running]:
    github.com/yetone/magpie/internal/sessions.refresh.func5(...)
    	github.com/yetone/magpie/internal/sessions/sessions.go:886
    github.com/yetone/magpie/internal/sessions.refresh(...)
    	github.com/yetone/magpie/internal/sessions/sessions.go:900 +0x11cd
    github.com/yetone/magpie/internal/sessions.statsIn(...)
    	github.com/yetone/magpie/internal/sessions/stats.go:143 +0x4bf
    github.com/yetone/magpie/internal/sessions.StatsAndNative(...)
    	github.com/yetone/magpie/internal/sessions/stats.go:117 +0x85
    github.com/yetone/magpie/internal/gui.combinedSessionStats(...)
    	github.com/yetone/magpie/internal/gui/sessions.go:466 +0x7e
    github.com/yetone/magpie/internal/gui.statsFor(...)
    	github.com/yetone/magpie/internal/gui/sessions.go:443 +0x272
    github.com/yetone/magpie/internal/gui.warmSessions.func1.1.warmSteps.1(...)
    	github.com/yetone/magpie/internal/gui/sessions.go:507 +0x15
    github.com/yetone/magpie/internal/gui.warmUp(...)
    	github.com/yetone/magpie/internal/gui/sessions.go:529 +0x29
    github.com/yetone/magpie/internal/gui.warmSessions.func1.1(...)
    	github.com/yetone/magpie/internal/gui/sessions.go:497 +0x50
    github.com/yetone/magpie/internal/sessions.Warm(...)
    	github.com/yetone/magpie/internal/sessions/quiet.go:31 +0x5a
    github.com/yetone/magpie/internal/gui.warmSessions.func1(...)
    	github.com/yetone/magpie/internal/gui/sessions.go:497 +0x25
    created by github.com/yetone/magpie/internal/gui.warmSessions in goroutine 1
    	github.com/yetone/magpie/internal/gui/sessions.go:493 +0x36
    
  13. nativeas commented on Oct 20, 2026

    @nativeas

    @JoeyWu-tech 这边找到另一个具体的重复路径来源了:Hermes 的同一个 SQLite 数据库里,有两条字节内容相同的 session ID,一条以 TEXT 存储,另一条以 BLOB 存储。 不需要配置共用目录或设置环境变量也能触发。

    以下已脱敏,不包含真实 session ID、本地路径、聊天内容、账号或数据库附件。

    发现与源码分析

    • sessions.id 声明为 TEXT PRIMARY KEY,但数据库里实际同时存在 TEXT 和 BLOB 两种存储类型的同名 ID。PRAGMA quick_check 返回 ok,所以这并非该检查能发现的数据库结构损坏。
    • hermesFiles() 把 id 扫描到 Go string;TEXT 和包含相同字节的 BLOB 都变成同一个字符串,因此生成相同的虚拟路径 <hermes-db>#<session-id>。
    • 从 v0.1.1294 源码看,两个引用会在 refresh 标记 parsing[path] 前进入待处理列表。后面共用/覆盖同一个 channel 条目,第一个 publish 关闭并删除它,第二个 publish 就在 sessions.go:886 执行 close(nil)。这与本机实际 panic 栈一致。

    对照实验(官方 macOS arm64 v0.1.1294)

    条件 实际结果
    备份并清空 Magpie 自身配置、缓存和 WebView 数据,保留原 agent 历史 仍然出现同一 panic,随后恢复原数据
    使用临时 Magpie 配置,进程内将 HERMES_HOME 指向空目录 持续运行 45 秒,观察结束后主动关闭
    同类临时配置,恢复默认 Hermes 来源作为对照 约 6 秒后退出,退出码 2,同一 panic
    将 HERMES_HOME 指向原数据库的一致性副本 约 6 秒后退出,退出码 2,同一 panic
    同一数据库副本,仅去掉上述重复 BLOB session 行 持续运行 45 秒,观察结束后主动关闭

    这些是本地读取实际历史的隔离实验,不是修改 Magpie 源码后的测试。

    已验证的本地绕过结果

    完整备份并校验数据库后,进一步检查了异常 BLOB ID:消息表、用量表及已检查的 session 关联字段中没有对该 BLOB ID 的精确引用。仅移除这一条异常 BLOB session 记录,保留正常 TEXT session;其关联消息数量在事务前后完全一致。

    随后安装官方 v0.1.1296,实际连续运行超过 90 秒,并打开会话页面成功加载 Hermes 会话,没有再出现该 panic。

    这只证明本机数据绕过有效:没有在修复原始数据前单独验证 v0.1.1296,也没有测试你提供的修复分支,不能据此认定上游问题已修复。 异常 BLOB 行最初是如何写入的仍未知。这里也不建议其他用户照搬删除操作,其他数据库可能有不同的关联数据。

    无隐私数据的最小 SQLite 示例

    下面只操作内存数据库,能演示为什么声明了 TEXT 主键仍会出现两条归一化后相同的 ID;它不是完整的 Magpie 崩溃回归测试:

    import sqlite3
    
    db = sqlite3.connect(':memory:')
    db.execute('CREATE TABLE sessions (id TEXT PRIMARY KEY)')
    db.execute('INSERT INTO sessions VALUES (?)', ('example-session',))
    db.execute('INSERT INTO sessions VALUES (?)', (b'example-session',))
    
    print(db.execute(
        'SELECT typeof(id), CAST(id AS TEXT) FROM sessions'
    ).fetchall())
    # [('text', 'example-session'), ('blob', 'example-session')]

    可以把这种 TEXT/BLOB 混合 ID 的情况加入 Hermes 列表或 refresh 去重的回归用例。即使异常数据来源尚未查清,归一化后的相同虚拟路径也不应让整个应用退出。

  14. 8 remaining items

  15. JoeyWu-tech commented on Oct 21, 2026

    @JoeyWu-tech
    Contributor

    @mxl2498 谢谢,堆栈和绕过方法都很有用,--gateway 也会崩这点我之前没注意到。

    小更正一下 commit 号:fbd99cb 那个 main 已经自己合了(9afdeb89),所以我把分支 rebase 了,现在是 fix/2932-rebased 上三个 commit,头是 7cc938ca,内容就是你说的那三处修复。两个变量指向同一个 .workbuddy 的情况我昨天按 @Tsuki-hash 的环境单独测过,分支上每个会话只算一次,main 上就是你这个 panic。刚又核了一遍,现在的 main ba319a75 上能直接打。

  16. cunnak commented on Oct 21, 2026

    @cunnak

    Another Windows data point — and a slightly different trigger vector than the installer-written variables reported above.

    Repro (100%, every launch): magpie-windows-amd64.exe, v0.1.1307 and v0.1.1308, Windows 11. Panic ~4-5s after start, exit code 2, identical stack to this issue (refresh.func5 → sessions.go:889, warmSessions → sessions.Warm → StatsAndNative → refresh). Happens in both magpie web and GUI mode.

    Trigger on this machine: CODEBUDDY_CONFIG_DIR and WORKBUDDY_CONFIG_DIR are both set to the same directory (C:\Users<user>.workbuddy) — but unlike the installer-written case, these are injected at runtime by the WorkBuddy/CodeBuddy IDE host process into its child processes. The User and Machine registry scopes are both empty, so any app launched from the IDE's integrated terminal inherits the collision even on machines where no installer wrote these variables. CodeBuddyDir() == WorkBuddyDir() → the same .jsonl sessions listed twice → duplicate path → close(nil channel), exactly as analyzed above.

    Verified workarounds:

    1. Clearing CODEBUDDY_CONFIG_DIR (empty value) before launch makes v0.1.1307 AND v0.1.1308 start and serve the gateway normally (127.0.0.1:3425 → 200, /v1/models returns the model list). This is the cheapest fix for affected users.
    2. MAGPIE_NO_ACCOUNTS=1 does NOT help — the panic is unrelated to account discovery.
    3. Downgrading to v0.1.1290 works (currently kept as a fallback binary).

    Also confirming: plain CLI commands (magpie ls, magpie providers, magpie update, …) never panic in the same poisoned environment — only the GUI/web/tray startup path goes through the session warm-up.

    Since the dedup patch on fix/2932-rebased would presumably cover this vector too, posting in case it helps push the merge. The runtime-injection angle may be worth a line in the release notes when it ships, since Windows users hitting this won't find anything in their registry to clean up. Happy to provide more logs if useful.

  17. JoeyWu-tech commented on Oct 21, 2026

    @JoeyWu-tech
    Contributor

    @cunnak thanks, the IDE-injected angle is a good catch. That one would leave people with nothing to clean up in the registry.

    Yes, the branch covers it. The fix doesn't care where the variables come from: it dedupes by the folder itself (os.SameFile), so two settings pointing at one .workbuddy get read once whether an installer wrote them or the IDE host passed them down. I tested that exact state yesterday (both vars on one moved folder): one session each on 7cc938ca, the same panic on main. Still applies cleanly to today's main f5b01574.

  18. Tsuki-hash commented on Oct 21, 2026

    @Tsuki-hash

    @mxl2498 谢谢这份 Windows 复现,web --gateway 那条我这边也当成覆盖面的补充记下了。有一个前提要更正一下,免得后面看的人照着查错方向:

    main 里没有 MAGPIE_NO_SESSIONS 这个开关。 我把 internal/ 下所有 MAGPIE_* 环境变量扫了一遍,只有 MAGPIE_NO_ACCOUNTS(只关账号发现,internal/provider/discovery.go)和 MAGPIE_NO_STATS(只关遥测/partner 事件,internal/stats/stats.go),没有 NO_SESSIONS。所以 MAGPIE_NO_SESSIONS=1 不起作用不是漏洞,是它不存在;MAGPIE_NO_ACCOUNTS=1 对这条 panic 无效也是对的,因为它本来就不碰会话预热。

    顺带把 --gateway 说清楚:gui.warmSessions() 是启动 3 秒后无条件 go 出来的(internal/gui/sessions.go),不看 web / --gateway / GUI 哪种模式,所以只要那个进程活着就会走进 StatsAndNative -> refresh。换句话说,--gateway 崩不是第二个 bug,是同一条路径的另一个入口,fix/2932-rebased 三个 commit 一起就都盖住了。

    如果以后想给“会话读取”一个真正的开关(跳过预热/只读缓存),那是独立的功能请求,跟 #2932 这个修复拆开提更合适,别吊在同一个 issue 上等。

  19. yetone commented on Oct 22, 2026

    @yetone
    Owner

    Landed on main in 572a175, built on @JoeyWu-tech's fix/2932-rebased (7cc938c) and credited to him as co-author.

    • refresh now marks a file as being read the moment it picks it. If the same path is listed twice in one read, it is read once, and the second publish no longer closes a nil channel.
    • When CODEBUDDY_CONFIG_DIR points at WorkBuddy's folder (the same path, a link, or a different letter case on Windows), those sessions are read once, as WorkBuddy's. The folder is also shown once under the session folders.
    • A Hermes state.db that holds one id as a TEXT row and a BLOB row (@nativeas's case) gives one session. OpenCode lists such an id once too.

    Tests:

    • On main's code the new tests panic with the reported close of nil channel, both on macOS and on a Windows 11 box. The case where both variables point at one folder (as for @Tsuki-hash and @mxl2498) goes through StatsAndNative, the warm-up's own call.
    • With the fix, the whole internal/sessions package passes on Windows.
    • The full suite passes on macOS.

    Not tried yet: a real WorkBuddy or Hermes install, and starting the app on Windows. @TimWongUp, @tianhao2316-beep, @cunnak, @Tsuki-hash, @mxl2498, @nativeas: once a release includes it, please check that magpie stays up after it starts. I'm keeping this open until you confirm.

    Not fixed here: Pi/omp and Qoder/Qoder CN sharing one folder under different spellings are still listed twice, though they no longer crash. That is #3258.

  20. JoeyWu-tech commented on Oct 22, 2026

    @JoeyWu-tech
    Contributor

    谢谢 @yetone 收了,测试也补得比我全。

    @nativeas 说好的:修复(572a1757)从 v0.1.1320 开始就带上了,现在最新是 v0.1.1322。装上以后启动看看还会不会退出,有问题在这儿说一声。

  21. mxl2498 commented on Oct 23, 2026

    @mxl2498

    @yetone 按你的要求,在 Windows 11 + 真实 WorkBuddy 安装 环境下完整验证过了,修复确认生效,可以从我这边结掉这个 issue。

    环境

    • Windows 11 专业版(NT 10.0.26300),x64
    • magpie-windows-amd64.exe(桌面/GUI 版),同时跑 tray 常驻实例 + 一个独立的 web 进程
    • 触发用的就是原来那套"有毒"配置(见下),这次没有清空任何东西

    修复前(0.1.1306 / 0.1.1307)

    magpie web --lan --no-open
    

    打印出地址后几秒内进程退出,panic: close of nil channel,栈在 sessions.go:889 / sessions.go:903(refresh → publish),3430 端口始终起不来。

    当时的触发条件是这两个变量指向同一目录:

    CODEBUDDY_CONFIG_DIR=C:\Users\Administrator\.workbuddy
    WORKBUDDY_CONFIG_DIR=C:\Users\Administrator\.workbuddy
    

    补充一点:User / Machine 两个作用域里查都是空的,说明不是安装器写进注册表/用户变量的,而是 WorkBuddy 桌面端启动子进程时注入的——所以 Windows 上中招的人翻系统设置是找不到的(和 @cunnak 那条 IDE 注入的观察一致)。

    当时靠 CODEBUDDY_CONFIG_DIR= magpie web --lan 绕过。

    修复后(0.1.1325 → 0.1.1327)

    升级后直接跑同一条命令,不动任何环境变量:

    • 不再 panic,进程稳定存活(隔 15 秒复查两次都在)
    • 0.0.0.0:3430 正常监听
    • 手机连同一 WiFi 能打开页面,用量 / 配额 / 路由都能看
    • 顺带确认了你说的那条:magpie web --gateway --lan --no-open 同样不再崩——之前我以为是另一处,确认是同一条路径一起被盖住了

    另外提一句:更新到 0.1.1327 时旧的 web 进程被重启掉了(更新程序会接管重启),重新拉起即可,不是回归。

    更正我上一条的一处说法

    MAGPIE_NO_SESSIONS=1 是我写错了——main 里没有这个变量(如 @Tsuki-hash 所说,只有 MAGPIE_NO_ACCOUNTS 和 MAGPIE_NO_STATS)。它不是"无效",是根本不存在,当时真正起作用的只是清空 CODEBUDDY_CONFIG_DIR 那一步。现在连这一步也不需要了。

    辛苦 @JoeyWu-tech 和 @yetone,从报上去到修完两天不到,速度很顶。

  22. JoeyWu-tech commented on Oct 23, 2026

    @JoeyWu-tech
    Contributor

    @mxl2498 谢谢用真实的 WorkBuddy 环境跑了一遍,这个是我们这边一直没法测的,--gateway 也一起确认了正好。

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions