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
{{ message }}
Repository navigation
Desktop: custom project icons save but never render in projects list (v1.15.12) #29807
In the opencode desktop app, custom project icons are saved correctly but never rendered in the projects list — each project shows the default colored letter instead of the chosen image.
Repro: Edit a project → choose an image file as its icon → Save. The selection persists, but the projects list keeps showing the default letter.
Root cause (investigated)
The icon is persisted. In the desktop data store the project record contains:
i.e. the chosen image is stored as a base64 data-URI in icon.override, alongside a fallback icon.color. The projects-list UI appears to render the color fallback and never uses icon.override.
I verified this across 5 projects in ~/Library/Application Support/ai.opencode.desktop/opencode.workspace.*.dat:
icon size
type
fallback color
renders?
226 KB
PNG
pink
no
40 KB
JPEG
lime
no
30 KB
PNG
purple
no
19 KB
PNG
mint
no
3 KB
JPEG
pink
no
Every stored override is a valid, fully-decodable image (correct PNG/JPEG magic bytes). So:
Not a save bug — the data is correct and complete.
Not size-dependent — a 3 KB icon fails identically to a 226 KB one.
Not format-dependent — PNG and JPEG both fail.
No errors logged — main.log / renderer.log show only benign ResizeObserver loop… warnings and update checks; nothing about icon/image decode or render.
Conclusion: the projects-list icon component isn't consuming icon.override; it falls back to the colored letter.
OpenCode version
Desktop app v1.15.12 (mac arm64), channel latest (confirmed up to date; no newer version available).
Steps to reproduce
Open the opencode desktop app.
Edit a project and set its icon to an image file (PNG or JPEG), then Save.
Observe the projects list — it shows the default colored letter, not the chosen image.
(Optional) Inspect ~/Library/Application Support/ai.opencode.desktop/opencode.workspace.*.dat: the project record's icon.override contains the correct base64 data-URI.
Operating System
macOS 26.5 (arm64)
Notes
Data store path: ~/Library/Application Support/ai.opencode.desktop/. Happy to provide a sanitized sample record or logs if useful.
Update — root cause found (reverse-engineered the v1.17.18 desktop bundle)
My original "the UI ignores icon.override" theory was close but wrong in the
details. The real problem is that the desktop app reads the project icon from a
different store key than the one the icon-setting path writes to. Confirmed by
disassembling OpenCode.app/Contents/Resources/app.asar (v1.17.18) and by
inspecting my own ~/Library/Application Support/ai.opencode.desktop/opencode.workspace.*.dat.
There are two separate workspace stores
The app persists two independent per-workspace stores (see Persist.serverWorkspace):
workspace:project value shape: {"value":{"icon":{"color":...,"override":"data:..."},"commands":{},"name":""}}
workspace:icon value shape: {"value":"data:image/png;base64,..."}
The renderer reads from workspace:icon, not workspace:project
The child store that feeds the projects-list icon is built as:
constinitialMeta=meta[0].value;// workspace:project storeconstinitialIcon=icon2[0].value;// workspace:icon store
...
constchild2=createStore({project: "",projectMeta: initialMeta,icon: initialIcon,// <-- this is what renders
...
});
So the rendered icon comes only from the workspace:icon store. The icon.override inside workspace:project is never read for rendering.
The supported write path is projectIcon(directory, value), which correctly
writes the icon store:
The Edit → set icon UI action wrote the data-URI into workspace:project → value.icon.override (legacy location) instead of
calling projectIcon() / writing workspace:icon; or
There was a schema migration to the standalone icon store and existing
icons in workspace:project.icon.override were never migrated forward.
Either way, projects whose icon lives only in workspace:project.icon.override
render the colored-letter fallback, while a project with workspace:icon set
renders correctly. I confirmed this empirically: the one project on my machine
that had workspace:icon populated rendered its custom image; the five that only
had workspace:project.icon.override did not.
Confirmed workaround
Writing workspace:icon = {"value":"data:image/<type>;base64,<...>"} directly into
each project's opencode.workspace.<head>.<checksum>.dat (app fully quit, then
relaunched) makes all custom icons render immediately. The .dat filename is
derived by the app as:
Make the set-icon UI action call projectIcon(directory, dataUri) (i.e.
write the icon store), not workspace:project.icon.override; and/or
Add a one-time migration: on load, if workspace:icon.value is empty but workspace:project.value.icon.override is set, copy the override into the icon store (projectIcon(dir, override)) so existing users' icons appear
without manual intervention.
Environment: desktop app v1.17.18 (mac arm64), macOS 26.5. Original report was
v1.15.12; the two-store split is still present in 1.17.18.
Activity
github-actions commentedon May 29, 2026
This issue might be a duplicate of existing issues. Please check:
project.icon_url_overrideafter webview refresh — same root cause investigation (data stored as base64 in override field, but UI renders color fallback instead)Please check these issues and consider commenting there or linking them if your report covers the same underlying bug.
george-mcintyre commentedon Jul 11, 2026
Update — root cause found (reverse-engineered the v1.17.18 desktop bundle)
My original "the UI ignores
icon.override" theory was close but wrong in thedetails. The real problem is that the desktop app reads the project icon from a
different store key than the one the icon-setting path writes to. Confirmed by
disassembling
OpenCode.app/Contents/Resources/app.asar(v1.17.18) and byinspecting my own
~/Library/Application Support/ai.opencode.desktop/opencode.workspace.*.dat.There are two separate workspace stores
The app persists two independent per-workspace stores (see
Persist.serverWorkspace):workspace:projectvalue shape:{"value":{"icon":{"color":...,"override":"data:..."},"commands":{},"name":""}}workspace:iconvalue shape:{"value":"data:image/png;base64,..."}The renderer reads from
workspace:icon, notworkspace:projectThe child store that feeds the projects-list icon is built as:
So the rendered icon comes only from the
workspace:iconstore. Theicon.overrideinsideworkspace:projectis never read for rendering.The supported write path is
projectIcon(directory, value), which correctlywrites the
iconstore:So the bug is one of:
workspace:project→value.icon.override(legacy location) instead ofcalling
projectIcon()/ writingworkspace:icon; oriconstore and existingicons in
workspace:project.icon.overridewere never migrated forward.Either way, projects whose icon lives only in
workspace:project.icon.overriderender the colored-letter fallback, while a project with
workspace:iconsetrenders correctly. I confirmed this empirically: the one project on my machine
that had
workspace:iconpopulated rendered its custom image; the five that onlyhad
workspace:project.icon.overridedid not.Confirmed workaround
Writing
workspace:icon = {"value":"data:image/<type>;base64,<...>"}directly intoeach project's
opencode.workspace.<head>.<checksum>.dat(app fully quit, thenrelaunched) makes all custom icons render immediately. The
.datfilename isderived by the app as:
Suggested fix
projectIcon(directory, dataUri)(i.e.write the
iconstore), notworkspace:project.icon.override; and/orworkspace:icon.valueis empty butworkspace:project.value.icon.overrideis set, copy the override into theiconstore (projectIcon(dir, override)) so existing users' icons appearwithout manual intervention.
Environment: desktop app v1.17.18 (mac arm64), macOS 26.5. Original report was
v1.15.12; the two-store split is still present in 1.17.18.
github-actions commentedon Sep 10, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.