Repository navigation
Description
Summary
opencode upgrade --method curl fails on native Windows: the downloaded install script is written to a Windows path (C:\Users\<user>\.cache\opencode\update-XXXX\install) but executed through bash with the backslashes mangled, so bash reports No such file or directory.
Environment
- opencode version: 2.0.14 (upgrading to 2.0.15)
- OS: Windows_NT 10.0.26200 (win32 x64)
- Terminal: TERM=xterm-256color (TERM_PROGRAM/COLORTERM unset)
- Shell: cmd.exe (
C:\WINDOWS\system32\cmd.exe), PowerShell 5.1;bashon PATH resolves to WSLC:\Windows\System32\bash.exe - Install/channel: curl method, binary at
C:\Users\ming\.opencode\bin\opencode.exe - Active plugins: none found in global or project config
Reproduction
- On native Windows, install opencode with the curl method so the binary lives at
%USERPROFILE%\.opencode\bin\opencode.exe. - Ensure
bashon PATH is WSL'sC:\Windows\System32\bash.exe(or any bash that cannot parseC:\paths). - Run
opencode upgrade 2.0.15 --method curl.
Expected Behavior
The install script at C:\Users\<user>\.cache\opencode\update-XXXX\install is executed successfully and opencode is upgraded to 2.0.15.
Actual Behavior
Upgrade fails immediately with:
┌ Upgrade
│
● Using method: curl
│
● From 2.0.14 → 2.0.15
│
■ Upgrade failed
│
■ The OpenCode installer failed
│
│ /bin/bash: C:Usersming.cacheopencodeupdate-29WiNminstall: No such file or directory
│
│ Command opencode upgrade 2.0.15 --method curl
│ Retry Fix the issue above, then run opencode upgrade again.
The path shown by bash has had every backslash stripped (C:\Users\ming\.cache\opencode\update-29WiN\install → C:Usersming.cacheopencodeupdate-29WiNminstall), indicating the path is passed to bash unquoted, so backslashes are consumed as escape characters. Additionally, the bash found on PATH is WSL's bash, which cannot open C:\... paths at all (it would need /mnt/c/...), so even a correctly quoted Windows path would fail when resolved this way.
Additional Context
- Binary evidence from 2.0.14 (
opencode.exe): the curl upgrade path is hardcoded as two steps — (1) downloadhttps://opencode.ai/v2/installto<cache>/update-XXXX/install(error title "Could not download the OpenCode installer"), then (2) spawn["bash", <cached install script>, "--version", <target>, "--no-modify-path"](error title "The OpenCode installer failed"). There is no PowerShell/cmd fallback, so on Windows the method depends entirely onbashbeing resolvable. - The mangled path indicates the script path passes through an unquoted shell parse before reaching bash: every backslash in
C:\Users\ming\.cache\opencode\update-XXXX\installwas consumed as an escape character. This layer is independent of which bash binary is ultimately invoked. - If no
bashexists on PATH at all, step 2 fails even earlier with a spawn error (ENOENT / "The system cannot find the file specified") under the same "The OpenCode installer failed" title — i.e., removing bash does not make the command succeed; it only changes the failure mode. - The temporary directory
update-XXXXis cleaned up after the failure, so there is no leftover state. - The v2 install script (
https://opencode.ai/v2/install) works when run manually in Git Bash, since it downloads@opencode/[email protected]from npm (opencode upgrade --method curlappears to take a different path that breaks on Windows). - The v2.0.15 GitHub release has no binary assets (source only), so a curl-based upgrade must go through the v2 install script / npm distribution rather than
releases/download. - Reproducible consistently (path handling is platform-specific, not intermittent).
Activity
Tsuki-hash commentedon Sep 24, 2026
Root cause is which
bashgets spawned, not how the path is written. On Windows 11 26200: Git Bash runs a script atC:\Users\<name>\.cache\opencode\update-XXXX\installwithout complaint (exit 0), so the backslashes are not the problem. The WSL entry point atC:\Windows\System32\bash.exestrips them and exits 127 with exactly the message in this issue. Converting the path, as suggested here and in #50950, would make it worse: WSL bash then does run the script, and becauseinstallinstalls whateveruname -sreports, it fetches a Linux binary into the Windows install directory.Fixing it by asking each candidate shell which system it runs on and accepting only MINGW/MSYS/CYGWIN — the same classification
installuses — plus honoring the already-documentedOPENCODE_GIT_BASH_PATH, which the updater ignored. Claiming this unless someone is mid-flight; #50886 is the same root cause seen from the "bash is not installed at all" side, so whoever is on it: the shell choice is the thing to fix.@yveming thanks for the log evidence, it is what pinned this down.
Two corrections to what I wrote above. (1) I named
C:\Windows\System32\bash.exeas the WSL entry point; that file does exist on my machine, but the resolving stub varies by install - @jpgomezv documented below that on his it is...\WindowsApps\bash.exewith no System32 one at all. The rule to state is "the WSL bash answers whenever Git is not on PATH", not one fixed path. (2) I speculated that #50950's backslash-intact wording meant the script had been deleted between download and exec. @jpgomezv has since reproduced that exact text with the file verified present, so both wordings come from a WSL bash and no second cause is needed. #51038 is intended to cover both reports.jpgomezv commentedon Sep 25, 2026
Confirming the shell-choice diagnosis with diagnostics from this machine, plus one correction to the #50950 caveat.
bashresolves to WSL here, not Git BashGit Bash is installed at
C:\Program Files\Git\bin\bash.exe, but onlyGit\cmdis on PATH, sobashfalls through to the WSL alias.OPENCODE_GIT_BASH_PATHis unset here. (FYIC:\Windows\System32\bash.exedoes not exist on this machine — the stub is the WindowsApps alias.)#50950 does not need a second cause
I reproduced that exact text with the script present:
The file was verified present before and after. WSL bash words a Windows path like that with the backslashes intact, so nothing has to remove it between download and exec. Nothing on this machine touches
.cache\opencode\update-*.Small nuance for the fix
A Git-Bash-style conversion (
/c/Users/...) also fails in WSL bash with the same message — only/mnt/c/...would actually run it. So the MINGW/MSYS/CYGWIN guard is the right fix, but a naive conversion fails safe rather than installing a Linux binary.Reproduced on 2.0.12→2.0.14, 2.0.14→2.0.15 and 2.0.15→2.0.16 if you want another tester.
Tsuki-hash commentedon Sep 25, 2026
@jpgomezv 两条都收下:固定路径那条(你那台是
WindowsApps别名,不是 System32)和 #50950 的"文件被删"猜测(你在脚本在位的情况下复现出同样文本,直接排除)。我已经改掉自己在 #50924 上的说法,并把 #51038 描述里那句 caveat 换成了这段更正。你说的
/c/Users/...细节和我的观察一致:我这台机器上 Git Bash 对原生C:\...参数是直接接受的(exit 0),所以问题从来不在路径写法,而在选中了哪个 shell —— 这也是 #51038 用候选 shell 自己的uname -s做过滤、完全不做路径转换的原因。愿意做这个测试者,正好补上我缺的那块。改动在
packages/cli/src/services/updater.ts,分支Tsuki-hash:windows-installer-shell(PR #51038,basev2)。我这边没法端到端验证:本机没装 Bun,而且真跑升级会动到我自己的安装。你机器上值得看的两个点是:Git 只在Git\cmd进 PATH 的情况下,安装脚本是否由C:\Program Files\Git\bin\bash.exe执行;以及把 Git 从 PATH 完全摘掉后,是否得到那条具名错误(提示装 Git for Windows 或设OPENCODE_GIT_BASH_PATH),而不是现在的 127。EloyRD commentedon Sep 25, 2026
Reproduced on Windows with OpenCode v2.0.15 while upgrading to v2.0.16.
Installation:
C:\Users\USERNAME.opencode\bin\opencode.exe
Command:
opencode update
Error:
/bin/bash: C:UsersUSERNAME.cacheopencodeupdate-OxF0RGinstall:
No such file or directory
The path backslashes are stripped, matching this issue.
Tsuki-hash commentedon Sep 25, 2026
@EloyRD that is a second independent reproduction, and the stripped-backslash form matches the WSL entry point rather than Git Bash. One detail worth recording for triage:
opencode updateis an alias of the upgrade command (packages/cli/src/commands/commands.ts:62), and the alias routes into the sameUpdater.upgrade, so both spellings and the TUI "update available" dialog all go through the singlebashspawn inpackages/cli/src/services/updater.tsthat #51038 changes. Your install path (%USERPROFILE%\.opencode\bin\opencode.exe) is the curl layout, which is the method that spawns the installer script.Tsuki-hash commentedon Sep 26, 2026
@yveming bullet 2 says the backslash consumption is "independent of which bash binary is ultimately invoked". Worth settling, because if true then #51038 fixes only half of it. Three measurements of the same single argv element (
C:\Users\<name>\.cache\opencode\update-XXXX\install, spawned directly, no shell in between, no quoting in play):...\Git\usr\bin\bash.exeand...\Git\bin\bash.exe)C:\Windows\System32\bash.exe/bin/bash: C:Users\<name>...install: No such file or directory...\WindowsApps\bash.exe(@jpgomezv's machine)/bin/bash: C:\Users\<name>\...install: No such file or directorySo the two wordings are produced by two different WSL entry points, not by a quoting layer sitting before bash, and in both WSL cases the script file is present (@jpgomezv verified before and after). A Windows path with backslashes is not itself a failure - which binary receives it is the whole difference. That is why #51038 selects the shell by asking each candidate its own
uname -sand deliberately does no path rewriting: quoting the argument would still let WSL bash run the script, and theninstallreadsuname -sas Linux and drops a Linux binary into the Windows install directory.Your bullet 1 matches the shipped shape we read in
packages/cli/src/services/updater.tstoo, so the spawn being fixed is the same one.angeloruggieridj commentedon Sep 29, 2026
Independent reproduction, plus confirmation that the fix's "Git installed but absent from PATH" case resolves the failure.
Environment: Windows 11 Pro build 26200 (
Windows_NT 10.0.26200, x64), opencode v2.0.16 curl install at%USERPROFILE%\.opencode\bin\opencode.exe, launched fromcmd.exe.This machine has both WSL entry points present, and Git for Windows installed but its
binabsent from PATH (onlyGit\cmdis), sobashnever reaches Git Bash:Updater spawn from
~/.local/share/opencode/log/opencode.log:Result:
/bin/bash: C:Usersaruggieri.cacheopencodeupdate-UMO6llinstall: No such file or directory— the stripped-backslash form, matching the System32 stub in your table.Confirming the fix's key case: the installer script handed to
C:\Program Files\Git\bin\bash.exewith the nativeC:\...path runs correctly, no path conversion needed:So recovering Git Bash from
%ProgramFiles%\Git\binselects the right platform, and@opencode/[email protected]is published (registry returns 200).One gap the shell fix alone won't close (filing separately): on Windows the destination
opencode.exeis locked while opencode runs, so even a correct bash cannot replace it. While the TUI and the long-lived background service were up,[System.IO.File]::Open($exe,'Open','ReadWrite','None')failed with "being used by another process". Immaterial to the shell-selection fix, but it shares this code path.Tsuki-hash commentedon Sep 29, 2026
@angeloruggieridj thanks for the third independent reproduction — and for testing the exact edge case. "Git for Windows installed but
Git\binnot on PATH" is precisely what #51038 covers: the candidate list includes%ProgramFiles%\Git\bin\bash.exeeven when it isn't on PATH, and picks the first candidate whoseuname -sreports MINGW/MSYS/CYGWIN — matching your measurement that the nativeC:\...path works once the right bash runs it.Agreed on the write lock: it shares the code path but is a separate failure from shell selection, so tracking it separately in #52025 is the right call.