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.
Cloning omarchy.bar (or any third-party kind: bar plugin) never renders — required properties + broken Loader.Error fallback
Reported by cubicruler · filed Sep 1, 2026Closed upstream on 2026-09-20 by bjarneo via an automated message, as a duplicate of #6915 (R-1851). GitHub close reason: completed.
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?
- Not yet mapped to any requirement or component.
- 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?
- Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. No decision has been recorded yet.
Original report
System details: Omarchy 4.0.2-1, Hyprland 0.56.2, AMD Ryzen 7 8845HS / Radeon 780M (GMKtec NucBox K8 Plus), 4 monitors
omarchy plugin clone omarchy.bar followed by omarchy plugin enable <clone-id> leaves the system with no status bar on any monitor — not even a fallback to the built-in bar. Reproduces with a completely unmodified clone (no edits at all), so it isn't specific to any customization, and persists across omarchy restart shell.
Steps to reproduce
1. omarchy plugin clone omarchy.bar (auto-switches to the clone, e.g. sacha.bar)
2. hyprctl layers shows no omarchy-bar surface on any monitor; omarchy-shell shell debugBarGeometry returns []
3. omarchy plugin list still reports the clone as active: true
4. Full shell restarts don't recover it
Root cause (traced in shell.qml / plugins/bar/Bar.qml), two bugs stacking:
plugins/bar/Bar.qmldeclares its host-injected propertiesrequired:
required property string omarchyPath
required property var barWidgetRegistry
required property var barConfig but pluginBarLoader in shell.qml (~L247-260) loads it via Loader { source: shell.activeBarSourceUrl } and only assigns those properties afterward in onLoaded: shell.configureBar(item, ...). A Loader.source load can't satisfy required properties atomically, so construction fails and Loader.status becomes Loader.Error before configureBar() ever runs.
- The
Loader.Errorhandler meant to catch that and fall back is itself broken (shell.qmlL255-258, and the identical pattern again at L641-648 for panel plugins):
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 isn't a property or method on Loader (only Component has errorString()), so this throws ReferenceError: errorString is not defined (visible in the shell's own log) before shell.failedBarId gets set. Because failedBarId never updates, activeBarId's fallback logic (L180: selectedBarId !== failedBarId && selectedBarAvailable ? selectedBarId : defaultBarId) never triggers — activeBarId stays pointed at the broken clone forever, so the built-in bar's own loader never activates either. Total bar loss, no recovery, no visible warning.
The same broken errorString reference exists a second time at L641-648 for the generic panel-plugin Loader, so any third-party kind: panel plugin that fails to load likely hits the same silent-failure path instead of the intended warning + shell.hide(...).
Workaround: removing required from the three properties in a cloned Bar.qml (plain property ... : <default> instead) avoids bug #1 — configureBar() still assigns them correctly moments later. Confirmed this restores a fully working cloned bar.
Suggested fix: fix the errorString reference in both onStatusChanged handlers (e.g. via sourceComponent && sourceComponent.errorString ? sourceComponent.errorString() : "", or whatever Quickshell actually exposes for a load failure), so a broken bar/panel clone falls back cleanly with a visible warning instead of disappearing. Separately, Bar.qml's three host-injected properties probably shouldn't be required given how pluginBarLoader wires them up.
Happy to open a PR for the errorString fix if useful.
View raw text
**System details:** Omarchy 4.0.2-1, Hyprland 0.56.2, AMD Ryzen 7 8845HS / Radeon 780M (GMKtec NucBox K8 Plus), 4 monitors
`omarchy plugin clone omarchy.bar` followed by `omarchy plugin enable <clone-id>` leaves the system with **no status bar on any monitor** — not even a fallback to the built-in bar. Reproduces with a completely unmodified clone (no edits at all), so it isn't specific to any customization, and persists across `omarchy restart shell`.
**Steps to reproduce**
1. `omarchy plugin clone omarchy.bar` (auto-switches to the clone, e.g. `sacha.bar`)
2. `hyprctl layers` shows no `omarchy-bar` surface on any monitor; `omarchy-shell shell debugBarGeometry` returns `[]`
3. `omarchy plugin list` still reports the clone as `active: true`
4. Full shell restarts don't recover it
**Root cause** (traced in `shell.qml` / `plugins/bar/Bar.qml`), two bugs stacking:
1. `plugins/bar/Bar.qml` declares its host-injected properties `required`:
```qml
required property string omarchyPath
required property var barWidgetRegistry
required property var barConfig
```
but `pluginBarLoader` in `shell.qml` (~L247-260) loads it via `Loader { source: shell.activeBarSourceUrl }` and only assigns those properties afterward in `onLoaded: shell.configureBar(item, ...)`. A `Loader.source` load can't satisfy `required` properties atomically, so construction fails and `Loader.status` becomes `Loader.Error` before `configureBar()` ever runs.
2. The `Loader.Error` handler meant to catch that and fall back is itself broken (`shell.qml` L255-258, and the identical pattern again at L641-648 for panel plugins):
```qml
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` isn't a property or method on `Loader` (only `Component` has `errorString()`), so this throws `ReferenceError: errorString is not defined` (visible in the shell's own log) *before* `shell.failedBarId` gets set. Because `failedBarId` never updates, `activeBarId`'s fallback logic (L180: `selectedBarId !== failedBarId && selectedBarAvailable ? selectedBarId : defaultBarId`) never triggers — `activeBarId` stays pointed at the broken clone forever, so the built-in bar's own loader never activates either. Total bar loss, no recovery, no visible warning.
The same broken `errorString` reference exists a second time at L641-648 for the generic panel-plugin `Loader`, so any third-party `kind: panel` plugin that fails to load likely hits the same silent-failure path instead of the intended warning + `shell.hide(...)`.
**Workaround:** removing `required` from the three properties in a cloned `Bar.qml` (plain `property ... : <default>` instead) avoids bug #1 — `configureBar()` still assigns them correctly moments later. Confirmed this restores a fully working cloned bar.
**Suggested fix:** fix the `errorString` reference in both `onStatusChanged` handlers (e.g. via `sourceComponent && sourceComponent.errorString ? sourceComponent.errorString() : ""`, or whatever Quickshell actually exposes for a load failure), so a broken bar/panel clone falls back cleanly with a visible warning instead of disappearing. Separately, `Bar.qml`'s three host-injected properties probably shouldn't be `required` given how `pluginBarLoader` wires them up.
Happy to open a PR for the `errorString` fix if useful.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.
No decision has been recorded yet.