Repository navigation
Description
Problem
One malformed (or unreadable) custom theme file rejects the entire custom-theme discovery — every valid custom theme in every config directory is lost for the session.
packages/tui/src/theme/discovery.ts:17 (on main 618de2888fcf):
result[path.basename(file, ".json")] = JSON.parse(await readFile(file, "utf8")) as unknownThere is no per-file error isolation: readFile failures and JSON.parse failures propagate out of the sequential loops in discoverThemes (only the readdir at :8-11 is guarded, and only for ENOENT).
Verified reproduction (laptop probe, origin/main 618de28, run twice with identical results)
Probe importing discoverThemes verbatim from the main tree, with two directories each holding one valid theme:
- Control (all valid): resolves
{"good-a":{"source":"a"},"good-b":{"source":"b"}} - After adding one file
a/themes/broken.jsoncontaining{ not json: REJECTED —SyntaxError: JSON Parse error: Expected '}'atdiscovery.ts:17. Neither valid theme is returned, including the one in the untouched second directory.
Why it matters — both callers degrade badly
- Main TUI (
packages/tui/src/context/theme.tsx:160-166):syncCustomThemes()catches the rejection with.catch(() => setStore("active", "opencode"))— one bad file not only drops all custom themes, it silently overrides the user's configured theme selection back to the built-inopencodetheme. - Mini TUI (
packages/tui/src/mini/theme.ts:312):themeSource()awaitsdiscoverThemes(...)with no local guard; the rejection propagates to the caller's fallback, again losing every custom theme (including the requested one, even when the requested theme's own file is perfectly valid).
Custom themes are user-owned files in themes/ directories (global config + project .opencode/); a typo in one JSON file — the most likely state of a theme a user is actively editing — should cost that one theme, not all of them plus the user's selection. Sibling user-state parsers in the same package already isolate per-entry failures (e.g. parsePromptStash in packages/tui/src/prompt/stash.tsx skips bad lines; parsePromptInfo in history.tsx validates shape).
Acceptance criteria
discoverThemesresolves (does not reject) when an individual theme file is malformed JSON or unreadable; that file is skipped and all other valid themes, in all directories, are still returned with the existing directory-precedence behavior intact.- The skipped file's failure is diagnosable (named in a warning/log or otherwise surfaced — not silently swallowed without trace, if a suitable channel exists in the TUI; at minimum the behavior is pinned by tests).
- New tests in
packages/tui/test/theme.test.tsnext to the existingdiscoverThemesprecedence tests (~:126-150): malformed file in the first directory does not lose valid themes from either directory; malformed file that would shadow a valid same-named theme does not take the valid one down with it (decide and pin whether the earlier valid entry survives). - Existing theme tests pass.
Oracle: the existing discoverThemes precedence tests plus per-entry isolation precedent in the sibling TUI parsers (stash.tsx/history.tsx).
Activity
dezren39 commentedon Nov 5, 2026
🤖 Agent note · state: filed
618de2888fcf6e3eae88ffae3c97923a4b7e907din a laptop probe (~/git/fleet/probe-2026-11-04-creator-opencode-1935, probe script inprobe-2026-11-04-creator-opencode-1935b, run twice with identical results): control with two valid themes resolves both; adding onebroken.json({ not json) in the first directory REJECTS the wholediscoverThemescall with aSyntaxErroratdiscovery.ts:17, losing the valid theme in the untouched second directory too. Arepo-task/v1small-fix packet is enqueued as task 9797 (queuerepo-health-opencode-pilot, deduperepo-health:v1:fix:developing-today/opencode:issue:1683— the queue validator still requires the pre-move repo name in packets; packet filehidden_files/packet-opencode-1683.json).discoverThemes(skip the bad file, keep every other valid theme and the directory precedence), with regression tests inpackages/tui/test/theme.test.ts; done when one malformed theme file no longer loses all custom themes or resets the active theme.hidden_files/issue-opencode-theme-discovery-malformed.md(goal workspace); sibling per-entry isolation precedent:packages/tui/src/prompt/stash.tsx/history.tsxdezren39 commentedon Nov 5, 2026
Task 9797 picked up by repo-worker-opencode on lane 3fe37e8a-c61b-419c-9e97-769ecd264d5d. Fresh GitHub checks confirm #1683 remains open and there is no matching PR. I will reproduce and fix per-file failures in discoverThemes, then add targeted theme tests.
dezren39 commentedon Nov 5, 2026
Task 9797 is parked for 20 minutes because PR #1721 has no GitHub checks reported yet. The change is pushed at 0a302ce; focused tests, TUI typecheck, lint (0 errors), and pre-push full typecheck are locally green. Resume by checking PR checks fresh, then merge only when green and the diff still matches #1683.
dezren39 commentedon Nov 5, 2026
🤖 Agent note · bound