You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bug Report: 07-devtools jq rewrite leaves a previously-corrupt opencode.json broken — sed fallback never runs as recovery
Severity: Medium Category: Installer / Error Handling Platform: All (Linux, macOS, Windows/WSL2) — confirmed on WSL2 Confidence: Confirmed
Follow-up to: #309 ([WSL2] Installer (07-devtools): reinstall corrupts opencode.json — sed strips trailing comma). #309 was closed by PR Light-Heart-Labs#901, but the fix has a recovery hole: it prevents NEW corruption but does not recover from EXISTING corruption left behind by the pre-Light-Heart-Labs#901 sed.
Description
PR Light-Heart-Labs#901 fixed the WRITE path in 07-devtools.sh so new installs don't corrupt opencode.json by eating trailing commas. But it doesn't recover from EXISTING corruption: when jq is installed AND the existing opencode.json is already malformed (e.g. left over from a pre-Light-Heart-Labs#901 install), jq's parse fails on the input file and the fix logs ai_warn "OpenCode config jq rewrite failed; leaving existing config in place" and keeps the broken file. The narrow-sed fallback only runs in the else branch (no jq present) — it never runs as recovery for jq parse failure.
Effect: users who upgrade from a pre-Light-Heart-Labs#901 broken state are stuck with a permanently broken OpenCode config. They don't get out of it without manual intervention.
Affected File(s)
dream-server/installers/phases/07-devtools.sh:156-174 — the if command -v jq >/dev/null 2>&1 block in the "Reinstall: update API key and URL in existing config" branch.
Root Cause
The "if jq is installed AND jq succeeds" path is two nested ifs, but the fallback to sed lives only in the OUTER else (no jq), not in the INNER else (jq present but failed):
ifcommand -v jq >/dev/null 2>&1;then
_opencode_tmp="$OPENCODE_CONFIG_DIR/opencode.json.tmp.$$"if jq --arg url ... '...'"$OPENCODE_CONFIG_DIR/opencode.json">"$_opencode_tmp";then
mv "$_opencode_tmp""$OPENCODE_CONFIG_DIR/opencode.json"
ai_ok "OpenCode config updated (API key and URL refreshed)"else
rm -f "$_opencode_tmp"
ai_warn "OpenCode config jq rewrite failed; leaving existing config in place"# ← BUG: no fall-through to sed fallback. The broken file is preserved.fielse# narrow-sed fallback — only runs when jq is ABSENT (not when jq parse fails)
_sed_i "s|\"apiKey\": *\"[^\"]*\"|\"apiKey\": \"${_opencode_key}\"|""..."
_sed_i "s|\"baseURL\": *\"[^\"]*\"|\"baseURL\": \"${_opencode_url}\"|""..."
ai_ok "OpenCode config updated (API key and URL refreshed)"fi
Evidence
In the test environment, the previous install (pre-Light-Heart-Labs#901) had left behind a corrupt ~/.config/opencode/opencode.json with the exact symptom #309 described — baseURL and apiKey siblings without a separator comma between them:
Phase 07-devtools enters the "Reinstall" branch (file exists) and the jq path (jq is installed).
Install log line 101: ⚠ OpenCode config jq rewrite failed; leaving existing config in place.
The broken file is unchanged. OpenCode CLI is still broken until the user manually deletes the file.
Impact
Medium. New installs from a clean state are unaffected by this issue — those go through the inline HEREDOC template at the top of the same function and produce a valid file. Only the upgrade path from a pre-Light-Heart-Labs#901 broken state is affected. But once a user is in this state, they don't get out of it without rm ~/.config/opencode/opencode.json and a re-run.
This is the kind of bug that produces "the installer says it succeeded but my devtools are still broken" support issues.
Suggested Approach
Option A (least invasive) — chain the sed fallback into the jq-failure branch by collapsing the two branches:
ifcommand -v jq >/dev/null 2>&1&& jq --arg url ... '...'"$OPENCODE_CONFIG_DIR/opencode.json">"$_opencode_tmp";then
mv "$_opencode_tmp""$OPENCODE_CONFIG_DIR/opencode.json"
ai_ok "OpenCode config updated (API key and URL refreshed)"else
rm -f "$_opencode_tmp"2>/dev/null
# narrow-sed fallback — runs when jq is absent OR when jq parse fails
_sed_i "s|\"apiKey\": *\"[^\"]*\"|\"apiKey\": \"${_opencode_key}\"|""..."
_sed_i "s|\"baseURL\": *\"[^\"]*\"|\"baseURL\": \"${_opencode_url}\"|""..."
ai_ok "OpenCode config updated (API key and URL refreshed)"fi
Caveat: this still leaves a broken file unchanged if the corruption is structural enough that the narrow-sed regexes don't match either (e.g. the missing comma in the test repro means the line containing apiKey doesn't quite match the sed pattern's whitespace expectations).
Option B (most robust) — when jq fails to parse, write a fresh config from the inline HEREDOC template at the top of the same function. This guarantees recovery from any prior corruption regardless of structure. Slightly more invasive but the only option that's actually deterministic.
I'd recommend B for predictability. A is fine if maintainers prefer minimal-diff fixes.
Filed during full-stack integration test of open PR stack Light-Heart-Labs#893–909 on Light-Heart-Labs/DreamServer@c0600ca3. Environment: WSL2 / Ubuntu 24.04 / jq 1.7.
Bug Report: 07-devtools jq rewrite leaves a previously-corrupt opencode.json broken — sed fallback never runs as recovery
Severity: Medium
Category: Installer / Error Handling
Platform: All (Linux, macOS, Windows/WSL2) — confirmed on WSL2
Confidence: Confirmed
Description
PR Light-Heart-Labs#901 fixed the WRITE path in
07-devtools.shso new installs don't corruptopencode.jsonby eating trailing commas. But it doesn't recover from EXISTING corruption: when jq is installed AND the existingopencode.jsonis already malformed (e.g. left over from a pre-Light-Heart-Labs#901 install), jq's parse fails on the input file and the fix logsai_warn "OpenCode config jq rewrite failed; leaving existing config in place"and keeps the broken file. The narrow-sed fallback only runs in theelsebranch (no jq present) — it never runs as recovery for jq parse failure.Effect: users who upgrade from a pre-Light-Heart-Labs#901 broken state are stuck with a permanently broken OpenCode config. They don't get out of it without manual intervention.
Affected File(s)
dream-server/installers/phases/07-devtools.sh:156-174— theif command -v jq >/dev/null 2>&1block in the "Reinstall: update API key and URL in existing config" branch.Root Cause
The "if jq is installed AND jq succeeds" path is two nested ifs, but the fallback to sed lives only in the OUTER
else(no jq), not in the INNERelse(jq present but failed):Evidence
In the test environment, the previous install (pre-Light-Heart-Labs#901) had left behind a corrupt
~/.config/opencode/opencode.jsonwith the exact symptom #309 described —baseURLandapiKeysiblings without a separator comma between them:{ ... "options": { "baseURL": "http://127.0.0.1:11434/v1" "apiKey": "no-key" }, ... }After running
bash install.sh --all --non-interactive --no-comfyuifrom a branch with PR Light-Heart-Labs#901 merged, install log line 101:The corrupt file is unchanged (mtime is still from the previous install). Manual jq reproduction:
jq -V→jq-1.7.Platform Analysis
aptand is installed via the same phase that runs this code.Reproduction
~/.config/opencode/opencode.json(e.g. produced byLight-Heart-Labs/main< fix(07-devtools): preserve trailing comma when rewriting opencode.json Light-Heart-Labs/DreamServer#901 — the original sed bug from [WSL2] Installer (07-devtools): reinstall corrupts opencode.json — sed strips trailing comma → invalid JSON, opencode-web crash-loops #309). The exact corruption: missing comma between sibling JSON keys, breaking parse at line 11 col 16.bash install.sh --all --non-interactivefrom a branch with fix(07-devtools): preserve trailing comma when rewriting opencode.json Light-Heart-Labs/DreamServer#901 merged.⚠ OpenCode config jq rewrite failed; leaving existing config in place.Impact
Medium. New installs from a clean state are unaffected by this issue — those go through the inline HEREDOC template at the top of the same function and produce a valid file. Only the upgrade path from a pre-Light-Heart-Labs#901 broken state is affected. But once a user is in this state, they don't get out of it without
rm ~/.config/opencode/opencode.jsonand a re-run.This is the kind of bug that produces "the installer says it succeeded but my devtools are still broken" support issues.
Suggested Approach
Option A (least invasive) — chain the sed fallback into the jq-failure branch by collapsing the two branches:
Caveat: this still leaves a broken file unchanged if the corruption is structural enough that the narrow-sed regexes don't match either (e.g. the missing comma in the test repro means the line containing
apiKeydoesn't quite match the sed pattern's whitespace expectations).Option B (most robust) — when jq fails to parse, write a fresh config from the inline HEREDOC template at the top of the same function. This guarantees recovery from any prior corruption regardless of structure. Slightly more invasive but the only option that's actually deterministic.
I'd recommend B for predictability. A is fine if maintainers prefer minimal-diff fixes.
Cross-references
Filed during full-stack integration test of open PR stack Light-Heart-Labs#893–909 on
Light-Heart-Labs/DreamServer@c0600ca3. Environment: WSL2 / Ubuntu 24.04 / jq 1.7.