Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A 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.

Inbox
ReportR-4807GitHub issuePublicReceived

Cloning the bar plugin leaves the system with no bar (required properties + broken error fallback)

Reported by aspinalljohn · 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.

Received and recorded verbatim. Nothing has been checked yet.

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

Cloning the bar plugin leaves the system with no bar (required properties + broken error fallback)revision 1 · captured 2026-10-04 12:03 UTC via poll

What happened

Running omarchy plugin clone omarchy.bar — a documented customization workflow — leaves the system with no bar at all. The cloned bar fails to load, and the intended fallback to the stock bar also fails, so nothing renders. It stays gone across omarchy restart shell.

The clone itself is unmodified at this point: the failure happens with a byte-for-byte copy of shell/plugins/bar/Bar.qml.

Expected

Either the cloned bar loads and renders identically to the stock bar, or (if it can't load) the documented fallback in shell.qml puts omarchy.bar back on screen.

Root cause

Two separate bugs stack up.

1. A plugin bar can never satisfy `required property`.

shell/plugins/bar/Bar.qml declares three required properties:

required property string omarchyPath      // :15
required property var barWidgetRegistry   // :17
required property var barConfig           // :22

The stock bar is instantiated from defaultBarComponent (shell.qml:225), which sets all three inline at construction — fine.

A plugin bar goes through pluginBarLoader (shell.qml:246) instead, which loads by URL and assigns the properties afterwards:

source: shell.activeBarId !== shell.defaultBarId ? shell.activeBarSourceUrl : ""
asynchronous: true
onLoaded: shell.configureBar(item, shell.activeBarManifest)

Loader.source has no way to supply required properties at creation, so instantiation fails before configureBar() (shell.qml:214) ever runs:

WARN scene: file:///home/john/.config/omarchy/plugins/john.bar/Bar.qml[15:3]: Required property omarchyPath was not initialized
WARN scene: file:///home/john/.config/omarchy/plugins/john.bar/Bar.qml[22:3]: Required property barConfig was not initialized
WARN scene: file:///home/john/.config/omarchy/plugins/john.bar/Bar.qml[17:3]: Required property barWidgetRegistry was not initialized

2. The error handler throws, so the fallback never happens.

shell.qml:254:

onStatusChanged: {
  if (status === Loader.Error) {
    var detail = errorString && errorString() ? errorString() : ""   // :256
    console.warn(...)
    shell.failedBarId = shell.activeBarId                            // :258
  }
}

Loader has no errorString member (that's QQmlComponent), so line 256 throws:

WARN scene: @shell.qml[256:-1]: ReferenceError: errorString is not defined

Line 258 never executes, so failedBarId stays "". activeBarId (shell.qml:180) therefore keeps resolving to the broken plugin bar, defaultBarLoader stays inactive (shell.qml:240), and the user is left with no bar — rather than the graceful degradation the code clearly intends.

Steps to reproduce

  1. On a stock install, run omarchy plugin clone omarchy.bar

→ "Cloned omarchy.bar to ~/.config/omarchy/plugins/<user>.bar and switched to <user>.bar"
2. The bar disappears immediately. omarchy restart shell does not bring it back.
3. journalctl --user -e | grep Bar.qml shows the three required-property warnings plus the errorString ReferenceError.

Verified against main

Not just the installed version — I fetched both files from basecamp/omarchy@main and the code is identical, at the same line numbers (Bar.qml:15,17,22 and shell.qml:250,256).

Workaround

Relaxing the three declarations in the clone makes it load correctly, since configureBar() assigns all three post-load anyway:

property string omarchyPath: ""
property var barWidgetRegistry: null
property var barConfig: null

barConfig is already null-safe at its use site (Util.isPlainObject(barConfig) ? barConfig : fallbackBarConfig, Bar.qml:375). barWidgetRegistry is dereferenced unguarded at Bar.qml:1584 (root.barWidgetRegistry.widgets), so it needs a guard to be safe during the window before configureBar() runs.

Bug 2 is worth fixing regardless of bug 1: any plugin bar that fails to load for any reason currently takes the whole bar down instead of falling back.

System

Omarchy4.0.1-2
HardwareApple MacBook Pro 14" (M1 Pro, 2021), aarch64 (Asahi)
Kernel7.1.6-1-1-ARCH
Hyprland0.56.1
Quickshell0.3.1 (Arch)
Qtqt6-base 6.11.2-3
View raw text
### What happened

Running `omarchy plugin clone omarchy.bar` — a documented customization workflow — leaves the system with **no bar at all**. The cloned bar fails to load, and the intended fallback to the stock bar also fails, so nothing renders. It stays gone across `omarchy restart shell`.

The clone itself is unmodified at this point: the failure happens with a byte-for-byte copy of `shell/plugins/bar/Bar.qml`.

### Expected

Either the cloned bar loads and renders identically to the stock bar, or (if it can't load) the documented fallback in `shell.qml` puts `omarchy.bar` back on screen.

### Root cause

Two separate bugs stack up.

**1. A plugin bar can never satisfy `required property`.**

`shell/plugins/bar/Bar.qml` declares three required properties:

```qml
required property string omarchyPath      // :15
required property var barWidgetRegistry   // :17
required property var barConfig           // :22
```

The stock bar is instantiated from `defaultBarComponent` (`shell.qml:225`), which sets all three inline at construction — fine.

A plugin bar goes through `pluginBarLoader` (`shell.qml:246`) instead, which loads by URL and assigns the properties *afterwards*:

```qml
source: shell.activeBarId !== shell.defaultBarId ? shell.activeBarSourceUrl : ""
asynchronous: true
onLoaded: shell.configureBar(item, shell.activeBarManifest)
```

`Loader.source` has no way to supply required properties at creation, so instantiation fails before `configureBar()` (`shell.qml:214`) ever runs:

```
WARN scene: file:///home/john/.config/omarchy/plugins/john.bar/Bar.qml[15:3]: Required property omarchyPath was not initialized
WARN scene: file:///home/john/.config/omarchy/plugins/john.bar/Bar.qml[22:3]: Required property barConfig was not initialized
WARN scene: file:///home/john/.config/omarchy/plugins/john.bar/Bar.qml[17:3]: Required property barWidgetRegistry was not initialized
```

**2. The error handler throws, so the fallback never happens.**

`shell.qml:254`:

```qml
onStatusChanged: {
  if (status === Loader.Error) {
    var detail = errorString && errorString() ? errorString() : ""   // :256
    console.warn(...)
    shell.failedBarId = shell.activeBarId                            // :258
  }
}
```

`Loader` has no `errorString` member (that's `QQmlComponent`), so line 256 throws:

```
WARN scene: @shell.qml[256:-1]: ReferenceError: errorString is not defined
```

Line 258 never executes, so `failedBarId` stays `""`. `activeBarId` (`shell.qml:180`) therefore keeps resolving to the broken plugin bar, `defaultBarLoader` stays inactive (`shell.qml:240`), and the user is left with no bar — rather than the graceful degradation the code clearly intends.

### Steps to reproduce

1. On a stock install, run `omarchy plugin clone omarchy.bar`
   → "Cloned omarchy.bar to ~/.config/omarchy/plugins/<user>.bar and switched to <user>.bar"
2. The bar disappears immediately. `omarchy restart shell` does not bring it back.
3. `journalctl --user -e | grep Bar.qml` shows the three required-property warnings plus the `errorString` ReferenceError.

### Verified against main

Not just the installed version — I fetched both files from `basecamp/omarchy@main` and the code is identical, at the same line numbers (`Bar.qml:15,17,22` and `shell.qml:250,256`).

### Workaround

Relaxing the three declarations in the *clone* makes it load correctly, since `configureBar()` assigns all three post-load anyway:

```qml
property string omarchyPath: ""
property var barWidgetRegistry: null
property var barConfig: null
```

`barConfig` is already null-safe at its use site (`Util.isPlainObject(barConfig) ? barConfig : fallbackBarConfig`, `Bar.qml:375`). `barWidgetRegistry` is dereferenced unguarded at `Bar.qml:1584` (`root.barWidgetRegistry.widgets`), so it needs a guard to be safe during the window before `configureBar()` runs.

Bug 2 is worth fixing regardless of bug 1: any plugin bar that fails to load for any reason currently takes the whole bar down instead of falling back.

### System

| | |
|---|---|
| Omarchy | 4.0.1-2 |
| Hardware | Apple MacBook Pro 14" (M1 Pro, 2021), aarch64 (Asahi) |
| Kernel | 7.1.6-1-1-ARCH |
| Hyprland | 0.56.1 |
| Quickshell | 0.3.1 (Arch) |
| Qt | qt6-base 6.11.2-3 |

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.