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.
Shell: third-party bar plugins never load — required properties are set after construction
Reported by andrepadez · filed Aug 15, 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
Summary
Any third-party plugin with "kinds": ["bar"] fails to load, leaving the desktop with no bar at all. This makes omarchy plugin clone omarchy.bar unusable: cloning the bar and switching to it silently removes the bar from every monitor.
The cloned file does not need to be modified — an unmodified, byte-identical copy of shell/plugins/bar/Bar.qml reproduces it.
Steps to reproduce
omarchy plugin clone omarchy.bar # clones to <user>.bar, sets bar.id in shell.json
omarchy plugin enable <user>.bar # see bug 2 below: clone does not do this itself
omarchy restart shellBar disappears from all monitors. Confirm no bar layer surfaces remain:
hyprctl layers | grep omarchy-bar # no outputExpected
The cloned bar renders identically to the built-in bar, since the QML is unchanged.
Actual
No bar on any monitor. journalctl --user:
WARN scene: file:///home/<user>/.config/omarchy/plugins/<user>.bar/Bar.qml[15:3]: Required property omarchyPath was not initialized
WARN scene: file:///home/<user>/.config/omarchy/plugins/<user>.bar/Bar.qml[17:3]: Required property barWidgetRegistry was not initialized
WARN scene: file:///home/<user>/.config/omarchy/plugins/<user>.bar/Bar.qml[22:3]: Required property barConfig was not initialized
WARN scene: @shell.qml[256:-1]: ReferenceError: errorString is not definedRoot cause
Bar.qml declares three required property values (omarchyPath, barWidgetRegistry, barConfig). QML requires these to be supplied at construction time.
The built-in bar satisfies that, because defaultBarComponent supplies them as initial bindings inside the Component (shell/shell.qml:226):
Component {
id: defaultBarComponent
Bar {
omarchyPath: shell.omarchyPath
barWidgetRegistry: shell.barWidgetRegistry
barConfig: shell.barConfig
...
}
}Third-party bars go through pluginBarLoader instead (shell/shell.qml:246), which sets source to a URL and only supplies the properties afterwards, in onLoaded → configureBar() (shell/shell.qml:214):
Loader {
id: pluginBarLoader
source: shell.activeBarId !== shell.defaultBarId ? shell.activeBarSourceUrl : ""
onLoaded: shell.configureBar(item, shell.activeBarManifest)
...
}
function configureBar(target, manifest) {
if ("omarchyPath" in target) target.omarchyPath = shell.omarchyPath
if ("barWidgetRegistry" in target) target.barWidgetRegistry = shell.barWidgetRegistry
if ("barConfig" in target) target.barConfig = shell.barConfig
...
}By the time onLoaded fires, construction has already failed. Assignment after the fact cannot satisfy a required property.
Suggested fix
Use Loader.setSource(url, initialProperties), which supplies properties during construction:
pluginBarLoader.setSource(shell.activeBarSourceUrl, {
omarchyPath: shell.omarchyPath,
barWidgetRegistry: shell.barWidgetRegistry,
barConfig: shell.barConfig,
shell: shell,
manifest: shell.activeBarManifest
})configureBar() can stay for the non-required properties.
Bug 2 — the failure is silent
shell/shell.qml:256 throws while trying to report the load error:
var detail = errorString && errorString() ? errorString() : ""errorString is not defined in that scope, so the Loader.Error handler raises ReferenceError before it can log which bar failed or set failedBarId. The intended fallback to the default bar therefore never happens either — the user gets no bar and no diagnostic. Loader in this context has no errorString(); the message needs to come from elsewhere (e.g. sourceComponent.errorString()), and the whole block wants a guard.
Fixing this alone would turn the bug above into a graceful fallback plus a clear log line.
Bug 3 — omarchy plugin clone leaves the clone disabled
omarchy plugin clone omarchy.bar writes "id": "<user>.bar" into bar in ~/.config/omarchy/shell.json and reports Now using <user>.bar as the bar, but the plugin is left disabled:
$ omarchy plugin list | grep '\.bar'
omarchy.bar enabled first-party bar Bar
<user>.bar disabled third-party bar My BarSo even with bugs 1 and 2 fixed, the freshly cloned bar would not load until the user separately runs omarchy plugin enable <user>.bar. clone should enable what it switches to, or not switch until enabled.
System details
| Omarchy | 4.0.0.alpha (4.0.0.r1744.gf002044-1) |
| Kernel | 7.1.8-arch1-3 |
| Hyprland | 0.56.2 |
| Quickshell | 0.3.0.r20.g28771c7-1 |
| CPU | AMD Ryzen 9 7940HS w/ Radeon 780M |
| GPU | AMD Phoenix1 (rev c1) |
| Monitors | 3 (2x 3840x2160 @1.5, 1x 2560x1440 @1.6) |
Reproduced on a multi-monitor setup, but nothing in the failure path looks monitor-dependent.
Context
I was cloning the bar to give each monitor its own bar font size — Style is a singleton, so font.base-size is global, and a bar that reads well on a 1600x900 logical screen is small on a 2560x1440 one. Per-screen scaling in a cloned bar is a reasonable way to do that, and the plugin system looks designed to allow it; it's just that no clone of a bar-kind plugin can load today.
Possibly related: #6913 (cloning a plugin from Setup → Plugins fails with unknown clone option: <id>). That one is a CLI invocation bug; this is a runtime load failure after a successful clone.
View raw text
## Summary
Any third-party plugin with `"kinds": ["bar"]` fails to load, leaving the desktop with no bar at all. This makes `omarchy plugin clone omarchy.bar` unusable: cloning the bar and switching to it silently removes the bar from every monitor.
The cloned file does not need to be modified — an unmodified, byte-identical copy of `shell/plugins/bar/Bar.qml` reproduces it.
## Steps to reproduce
```sh
omarchy plugin clone omarchy.bar # clones to <user>.bar, sets bar.id in shell.json
omarchy plugin enable <user>.bar # see bug 2 below: clone does not do this itself
omarchy restart shell
```
Bar disappears from all monitors. Confirm no bar layer surfaces remain:
```sh
hyprctl layers | grep omarchy-bar # no output
```
## Expected
The cloned bar renders identically to the built-in bar, since the QML is unchanged.
## Actual
No bar on any monitor. `journalctl --user`:
```
WARN scene: file:///home/<user>/.config/omarchy/plugins/<user>.bar/Bar.qml[15:3]: Required property omarchyPath was not initialized
WARN scene: file:///home/<user>/.config/omarchy/plugins/<user>.bar/Bar.qml[17:3]: Required property barWidgetRegistry was not initialized
WARN scene: file:///home/<user>/.config/omarchy/plugins/<user>.bar/Bar.qml[22:3]: Required property barConfig was not initialized
WARN scene: @shell.qml[256:-1]: ReferenceError: errorString is not defined
```
## Root cause
`Bar.qml` declares three `required property` values (`omarchyPath`, `barWidgetRegistry`, `barConfig`). QML requires these to be supplied **at construction time**.
The built-in bar satisfies that, because `defaultBarComponent` supplies them as initial bindings inside the `Component` (`shell/shell.qml:226`):
```qml
Component {
id: defaultBarComponent
Bar {
omarchyPath: shell.omarchyPath
barWidgetRegistry: shell.barWidgetRegistry
barConfig: shell.barConfig
...
}
}
```
Third-party bars go through `pluginBarLoader` instead (`shell/shell.qml:246`), which sets `source` to a URL and only supplies the properties afterwards, in `onLoaded` → `configureBar()` (`shell/shell.qml:214`):
```qml
Loader {
id: pluginBarLoader
source: shell.activeBarId !== shell.defaultBarId ? shell.activeBarSourceUrl : ""
onLoaded: shell.configureBar(item, shell.activeBarManifest)
...
}
function configureBar(target, manifest) {
if ("omarchyPath" in target) target.omarchyPath = shell.omarchyPath
if ("barWidgetRegistry" in target) target.barWidgetRegistry = shell.barWidgetRegistry
if ("barConfig" in target) target.barConfig = shell.barConfig
...
}
```
By the time `onLoaded` fires, construction has already failed. Assignment after the fact cannot satisfy a `required property`.
### Suggested fix
Use `Loader.setSource(url, initialProperties)`, which supplies properties during construction:
```qml
pluginBarLoader.setSource(shell.activeBarSourceUrl, {
omarchyPath: shell.omarchyPath,
barWidgetRegistry: shell.barWidgetRegistry,
barConfig: shell.barConfig,
shell: shell,
manifest: shell.activeBarManifest
})
```
`configureBar()` can stay for the non-required properties.
## Bug 2 — the failure is silent
`shell/shell.qml:256` throws while trying to report the load error:
```qml
var detail = errorString && errorString() ? errorString() : ""
```
`errorString` is not defined in that scope, so the `Loader.Error` handler raises `ReferenceError` before it can log which bar failed or set `failedBarId`. The intended fallback to the default bar therefore never happens either — the user gets no bar and no diagnostic. `Loader` in this context has no `errorString()`; the message needs to come from elsewhere (e.g. `sourceComponent.errorString()`), and the whole block wants a guard.
Fixing this alone would turn the bug above into a graceful fallback plus a clear log line.
## Bug 3 — `omarchy plugin clone` leaves the clone disabled
`omarchy plugin clone omarchy.bar` writes `"id": "<user>.bar"` into `bar` in `~/.config/omarchy/shell.json` and reports `Now using <user>.bar as the bar`, but the plugin is left `disabled`:
```
$ omarchy plugin list | grep '\.bar'
omarchy.bar enabled first-party bar Bar
<user>.bar disabled third-party bar My Bar
```
So even with bugs 1 and 2 fixed, the freshly cloned bar would not load until the user separately runs `omarchy plugin enable <user>.bar`. `clone` should enable what it switches to, or not switch until enabled.
## System details
| | |
|---|---|
| Omarchy | 4.0.0.alpha (`4.0.0.r1744.gf002044-1`) |
| Kernel | 7.1.8-arch1-3 |
| Hyprland | 0.56.2 |
| Quickshell | 0.3.0.r20.g28771c7-1 |
| CPU | AMD Ryzen 9 7940HS w/ Radeon 780M |
| GPU | AMD Phoenix1 (rev c1) |
| Monitors | 3 (2x 3840x2160 @1.5, 1x 2560x1440 @1.6) |
Reproduced on a multi-monitor setup, but nothing in the failure path looks monitor-dependent.
## Context
I was cloning the bar to give each monitor its own bar font size — `Style` is a singleton, so `font.base-size` is global, and a bar that reads well on a 1600x900 logical screen is small on a 2560x1440 one. Per-screen scaling in a cloned bar is a reasonable way to do that, and the plugin system looks designed to allow it; it's just that no clone of a `bar`-kind plugin can load today.
---
Possibly related: #6913 (cloning a plugin from Setup → Plugins fails with `unknown clone option: <id>`). That one is a CLI invocation bug; this is a runtime load failure after a successful clone.
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 04:06 UTC