Proof Portal
Omarchy
ProbeLabs65 findings · 95 requirementsA proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.
Notification image-path hint bypasses icon resolution, rendering Qt's missing-texture placeholder for themed icon names
Reported by MyGuyArrow · filed Sep 3, 2026Closed upstream on 2026-10-11 by the bot omarchybot, as a duplicate (target not recorded).
At a glance
- 1 · What is claimed?
- Only the report text below — no validator has restated it as checkable claims yet.
- 2 · What does it affect?
- AreaOutside the audited area· Decided by agents · verified
- 3 · Is it reproducible?
- No validation has been run yet.
- 4 · What remains unclear?
- Not validated yet: no claims, no reproducer.
- 5 · What happens next?
- Decided by agents and verified by a second, independent agent — see the decision.
Original report
What happened
A notification whose icon arrives via the `image-path` hint as a themed icon name renders Qt's magenta/black missing-texture placeholder in the icon slot.
This is the path notify-send -i <name> takes: libnotify puts the name in the image-path hint and leaves app_icon empty, so it affects any sender using notify-send with a themed name.
Steps to reproduce
notify-send -i definitely-not-an-installed-icon "Notification icon test" "Icon name is not in the icon theme"Expected
The icon slot is hidden, exactly as shell/plugins/notifications/components/NotificationCard.qml:116-118 intends:
Hide the slot when the icon failed to resolve (themed-icon name not in the user's icon theme) AND we don't have a glyph fallback — prevents rendering Qt's pink broken-image placeholder.
Actual
A magenta/black checkerboard is drawn in the icon slot.
Cause
NotificationCard.qml:39:
readonly property string smallIconSource: image.length > 0 ? image : iconSource(appIcon)iconSource() (line 58) is what resolves themed names and check-guards them:
function iconSource(icon) {
var value = String(icon || "")
if (value.length === 0) return ""
if (value.indexOf("file://") === 0 || value.indexOf("image://") === 0) return value
if (value.charAt(0) === "/") return Util.fileUrl(value)
return Quickshell.iconPath(value, true) // check flag -> "" when missing
}…but it is only applied to appIcon. image goes straight to Image.source, so a bare themed name is treated as a relative URL, fails to load, and Qt paints its placeholder. The slot's visibility guard doesn't suppress it because hasSmallIcon is true (image.length > 0).
Per the Desktop Notifications Specification, image-path is "a URI … or a name in a freedesktop.org-compliant icon theme" — so it needs the same resolution as app_icon.
Confirmed the hint with dbus-monitor:
method call ... member=Notify
string "notify-send"
uint32 0
string "" <- app_icon is empty
string "DBUS probe"
string "body"
array [ ]
array [
dict entry(
string "image-path"
variant string "definitely-not-an-installed-icon"
)
...
]In isolation Quickshell.iconPath("definitely-not-an-installed-icon", true) correctly returns "", so routing image through iconSource() looks sufficient:
readonly property string smallIconSource: image.length > 0 ? iconSource(image) : iconSource(appIcon)Also observed — same symptom, different trigger
A bare `app_icon` name also produced the placeholder when the name was absent from a stale /usr/share/icons/hicolor/icon-theme.cache, even though the PNGs were on disk. Concretely: Ghostty relays terminal notifications tagged app_icon=com.mitchellh.ghostty, and every such toast (Claude Code's among them) showed the checkerboard. pkexec gtk-update-icon-cache -f -t /usr/share/icons/hicolor fixed that case.
The cache went stale because Arch's gtk-update-icon-cache.hook triggers on usr/share/icons/*/ but excludes usr/share/icons/*/?*, so it never fires when a package adds icons into an existing theme tree. That part is not an Omarchy bug — but the placeholder rendering on an unresolvable app_icon name is the same guard failing, and I could not fully isolate why iconPath's check flag didn't suppress it in that state. Flagging it in case the fix should also harden the appIcon branch.
System
| Omarchy | 4.0.2-1 |
| Quickshell | 0.3.1-1 (Arch) |
| qt6-base | 6.11.2-2 |
| CPU | Intel Core Ultra 9 185H |
| GPU | Intel Arc (Meteor Lake-P) + NVIDIA RTX 4070 Max-Q |
| Icon theme | Yaru-sage-dark |
| Display scale | 2 |
View raw text
### What happened
A notification whose icon arrives via the **`image-path` hint** as a *themed icon name* renders Qt's magenta/black missing-texture placeholder in the icon slot.
This is the path `notify-send -i <name>` takes: libnotify puts the name in the `image-path` hint and leaves `app_icon` empty, so it affects any sender using `notify-send` with a themed name.
### Steps to reproduce
```bash
notify-send -i definitely-not-an-installed-icon "Notification icon test" "Icon name is not in the icon theme"
```
### Expected
The icon slot is hidden, exactly as `shell/plugins/notifications/components/NotificationCard.qml:116-118` intends:
> Hide the slot when the icon failed to resolve (themed-icon name not in the user's icon theme) AND we don't have a glyph fallback — prevents rendering Qt's pink broken-image placeholder.
### Actual
A magenta/black checkerboard is drawn in the icon slot.
### Cause
`NotificationCard.qml:39`:
```qml
readonly property string smallIconSource: image.length > 0 ? image : iconSource(appIcon)
```
`iconSource()` (line 58) is what resolves themed names and check-guards them:
```qml
function iconSource(icon) {
var value = String(icon || "")
if (value.length === 0) return ""
if (value.indexOf("file://") === 0 || value.indexOf("image://") === 0) return value
if (value.charAt(0) === "/") return Util.fileUrl(value)
return Quickshell.iconPath(value, true) // check flag -> "" when missing
}
```
…but it is only applied to `appIcon`. `image` goes straight to `Image.source`, so a bare themed name is treated as a relative URL, fails to load, and Qt paints its placeholder. The slot's visibility guard doesn't suppress it because `hasSmallIcon` is true (`image.length > 0`).
Per the [Desktop Notifications Specification](https://specifications.freedesktop.org/notification-spec/latest/hints.html), `image-path` is *"a URI … or a name in a freedesktop.org-compliant icon theme"* — so it needs the same resolution as `app_icon`.
Confirmed the hint with `dbus-monitor`:
```
method call ... member=Notify
string "notify-send"
uint32 0
string "" <- app_icon is empty
string "DBUS probe"
string "body"
array [ ]
array [
dict entry(
string "image-path"
variant string "definitely-not-an-installed-icon"
)
...
]
```
In isolation `Quickshell.iconPath("definitely-not-an-installed-icon", true)` correctly returns `""`, so routing `image` through `iconSource()` looks sufficient:
```qml
readonly property string smallIconSource: image.length > 0 ? iconSource(image) : iconSource(appIcon)
```
### Also observed — same symptom, different trigger
A bare **`app_icon`** name also produced the placeholder when the name was absent from a stale `/usr/share/icons/hicolor/icon-theme.cache`, even though the PNGs were on disk. Concretely: Ghostty relays terminal notifications tagged `app_icon=com.mitchellh.ghostty`, and every such toast (Claude Code's among them) showed the checkerboard. `pkexec gtk-update-icon-cache -f -t /usr/share/icons/hicolor` fixed that case.
The cache went stale because Arch's `gtk-update-icon-cache.hook` triggers on `usr/share/icons/*/` but excludes `usr/share/icons/*/?*`, so it never fires when a package adds icons into an existing theme tree. That part is not an Omarchy bug — but the placeholder rendering on an unresolvable `app_icon` name is the same guard failing, and I could not fully isolate why `iconPath`'s check flag didn't suppress it in that state. Flagging it in case the fix should also harden the `appIcon` branch.
### System
| | |
|---|---|
| Omarchy | 4.0.2-1 |
| Quickshell | 0.3.1-1 (Arch) |
| qt6-base | 6.11.2-2 |
| CPU | Intel Core Ultra 9 185H |
| GPU | Intel Arc (Meteor Lake-P) + NVIDIA RTX 4070 Max-Q |
| Icon theme | Yaru-sage-dark |
| Display scale | 2 |
Validation
Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.
Linked
Not linked to any known issue, other report or change yet.
Decision
Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.
- Out of scopeDecided by agents · verified · 2026-10-09 10:38 UTC