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.
Custom bar load failure can't fall back: pluginBarLoader.onStatusChanged throws ReferenceError on errorString
Reported by tinterian · filed Sep 5, 2026 · open at source
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
When a custom/third-party bar plugin (kind bar, selected via ~/.config/omarchy/shell.json or omarchy plugin clone) fails to load for any reason, Quickshell's shell host is supposed to fall back to the built-in omarchy.bar and log which plugin failed. Instead, the fallback never happens and the bar disappears entirely, because the error-handling code itself throws.
shell.qml's pluginBarLoader:
Loader {
id: pluginBarLoader
...
onStatusChanged: {
if (status === Loader.Error) {
var detail = errorString && errorString() ? errorString() : ""
console.warn("bar option " + shell.activeBarId + " failed to load, falling back to " + shell.defaultBarId + ":", detail)
shell.failedBarId = shell.activeBarId
}
}
}errorString is not a bound identifier anywhere in this scope, so evaluating it throws a ReferenceError, which aborts the handler before shell.failedBarId = shell.activeBarId runs. Since failedBarId never gets set, activeBarId (selectedBarId !== failedBarId && selectedBarAvailable ? selectedBarId : defaultBarId) never falls back to defaultBarId, so defaultBarLoader never activates either. Net effect: no bar renders at all, instead of gracefully reverting to the stock bar.
Steps to reproduce
omarchy plugin clone omarchy.bar(this alone is enough to trigger a load failure — see basecamp/omarchy#<omarchy-plugin-clone-required-property-issue>, filed separately)omarchy restart shellhyprctl layersshows noomarchy-barlayer surface on any level — the bar is completely gone rather than falling back to the built-in one.- Quickshell's log (
~/.local/state/XDG_RUNTIME_DIRquickshell instance log) shows, right after the plugin's own load warnings:
WARN scene: @shell.qml[256:-1]: ReferenceError: errorString is not definedExpected
The bar falls back to the built-in omarchy.bar, with a clear console warning naming the plugin that failed.
Actual
No bar renders at all, and the fallback's own error-reporting code throws before it can flip failedBarId.
System
- Omarchy: 4.0.0-1 (stable channel)
- Hyprland: 0.56.2
- Quickshell: 0.3.0 (quickshell-git AUR)
uname -a: Linux 7.1.8-arch1-3 x86_64
Suggested fix
Read the actual error from the Loader (e.g. pluginBarLoader.errorString if Quickshell's Loader type exposes it) instead of the bare, unbound errorString identifier — or drop the detail extraction and just log shell.activeBarSourceUrl.
View raw text
### What happened
When a custom/third-party bar plugin (kind `bar`, selected via `~/.config/omarchy/shell.json` or `omarchy plugin clone`) fails to load for any reason, Quickshell's shell host is supposed to fall back to the built-in `omarchy.bar` and log which plugin failed. Instead, the fallback never happens and the bar disappears entirely, because the error-handling code itself throws.
`shell.qml`'s `pluginBarLoader`:
```qml
Loader {
id: pluginBarLoader
...
onStatusChanged: {
if (status === Loader.Error) {
var detail = errorString && errorString() ? errorString() : ""
console.warn("bar option " + shell.activeBarId + " failed to load, falling back to " + shell.defaultBarId + ":", detail)
shell.failedBarId = shell.activeBarId
}
}
}
```
`errorString` is not a bound identifier anywhere in this scope, so evaluating it throws a `ReferenceError`, which aborts the handler *before* `shell.failedBarId = shell.activeBarId` runs. Since `failedBarId` never gets set, `activeBarId` (`selectedBarId !== failedBarId && selectedBarAvailable ? selectedBarId : defaultBarId`) never falls back to `defaultBarId`, so `defaultBarLoader` never activates either. Net effect: **no bar renders at all**, instead of gracefully reverting to the stock bar.
### Steps to reproduce
1. `omarchy plugin clone omarchy.bar` (this alone is enough to trigger a load failure — see basecamp/omarchy#<omarchy-plugin-clone-required-property-issue>, filed separately)
2. `omarchy restart shell`
3. `hyprctl layers` shows no `omarchy-bar` layer surface on any level — the bar is completely gone rather than falling back to the built-in one.
4. Quickshell's log (`~/.local/state`/`XDG_RUNTIME_DIR` quickshell instance log) shows, right after the plugin's own load warnings:
```
WARN scene: @shell.qml[256:-1]: ReferenceError: errorString is not defined
```
### Expected
The bar falls back to the built-in `omarchy.bar`, with a clear console warning naming the plugin that failed.
### Actual
No bar renders at all, and the fallback's own error-reporting code throws before it can flip `failedBarId`.
### System
- Omarchy: 4.0.0-1 (stable channel)
- Hyprland: 0.56.2
- Quickshell: 0.3.0 (quickshell-git AUR)
- `uname -a`: Linux 7.1.8-arch1-3 x86_64
### Suggested fix
Read the actual error from the `Loader` (e.g. `pluginBarLoader.errorString` if Quickshell's `Loader` type exposes it) instead of the bare, unbound `errorString` identifier — or drop the detail extraction and just log `shell.activeBarSourceUrl`.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:52 UTC