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-1279GitHub issuePublicFixed

omarchy-bar-text-color decodes every frame of a multi-frame background, exhausting system memory

Reported by GekkeTovie · filed Aug 29, 2026 · open at source

Decided: Out of scope — decided by agents · verified 3 days ago.

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

omarchy-bar-text-color decodes every frame of a multi-frame background, exhausting system memoryrevision 1 · captured 2026-09-28 21:24 UTC via poll

What's wrong?

omarchy-bar-text-color samples the average colour under the bar by handing the
current background straight to ImageMagick:

https://github.com/basecamp/omarchy/blob/master/bin/omarchy-bar-text-color

pixel=$(magick "$background_path" -auto-orient \
  -resize "${screen_width}x${screen_height}^" \
  -gravity center -extent "${screen_width}x${screen_height}" \
  -gravity NorthWest -crop "$crop" +repage \
  -resize '1x1!' -format '%[fx:int(255*r)],%[fx:int(255*g)],%[fx:int(255*b)]' info:-)

The only validation on the input is:

[[ -f $background_path ]] || fallback

That checks the background exists, never that it is a single still frame.
There is no frame selector, no MAGICK_MEMORY_LIMIT, and no timeout.

If the background is a multi-frame file, ImageMagick decodes every frame and
then runs the whole resize/crop pipeline over the full sequence. At 1080p that is
roughly 16 MB per frame, so a few thousand frames run into tens of GB. The -crop
that makes this cheap for a still image happens far too late to help.

On this machine the background symlink pointed at an .mp4. ImageMagick handed it
to its ffmpeg delegate, and memory went to the floor hard enough that unrelated
processes started dying.

What I expected

Sampling one row of pixels from the wallpaper should cost roughly one frame of
memory regardless of what the background file happens to be, and a background it
cannot cheaply sample should hit the existing fallback path.

Impact

This is not confined to the bar. Once free memory drops below the kernel's min
watermark, other processes fail:

Node 0 Normal free:17784kB min:62724kB low:634040kB high:1205356kB
magick: page allocation failure: order:0, mode:0xc0de0(GFP_KERNEL|__GFP_HIGH|__GFP_ZERO|__GFP_COMP|__GFP_NOMEMALLOC)
  folio_alloc_swap+0x19e/0x4f0
  shrink_folio_list+0x592/0xfd0

Order-0 allocations failing inside folio_alloc_swap means the kernel could not
obtain a single page in order to swap pages out. This was on a machine with 46 GB
of RAM and 46 GB of zram swap.

In a six-minute window that produced: 3 kernel page-allocation failures (plus ~27
more suppressed by warn_alloc), 2 magick SIGABRTs, and 3 Chromium renderer
SIGTRAPs. systemd-oomd logged "Considered 10 cgroups for killing" 482 times and
killed nothing; the kernel OOM killer never fired. Nothing gets killed — processes
abort themselves, so there is no OOM message pointing at the real cause.

Worth noting for anyone triaging a similar report: the Chromium crashes are
SIGTRAP with si_code: SI_KERNEL, and frame 0 disassembles to ud2 — that is
Chromium's IMMEDIATE_CRASH() on a failed allocation, i.e. Chromium deliberately
aborting, not a Chromium bug. They look alarming and are pure collateral.

Steps to reproduce

  1. Set "transparent": true for the bar in ~/.config/omarchy/shell.json (this

is what activates the omarchy-bar-text-color code path via
plugins/bar/Bar.qml → refreshTransparentForeground()).
2. Point ~/.local/state/omarchy/current/background at a multi-frame file — a
video, or an animated GIF.
3. Trigger a bar foreground refresh (theme change, bar position change, or
toggling transparency).
4. Watch RSS of the spawned magick process, and journalctl -k for
page allocation failure.

I reproduced the memory blow-up from the invocation alone; I did not deliberately
re-run it unbounded, since the first occurrence was enough to destabilise the
machine.

Suggested fix

Restricting ImageMagick to the first frame is a one-token change and fixes video,
animated GIF, multi-page TIFF and PDF in one go:

magick "${background_path}[0]" -auto-orient ...

Belt-and-braces would be to also bound the call, since the result is only ever
used to pick between two colours that already have a fallback:

MAGICK_MEMORY_LIMIT=256MiB MAGICK_MAP_LIMIT=256MiB timeout 10 magick "${background_path}[0]" ...

Both preserve the existing || true → fallback behaviour when anything fails.

System details

omarchy      4.0.1-1 (version file reports 4.0.0.alpha)
kernel       7.1.9-arch1-2
quickshell   0.3.1-1
hyprland     0.56.2-1
imagemagick  7.1.2.30-1
chromium     151.0.7922.173-1
board        MSI B550-A PRO (MS-7C56)
memory       46 GiB RAM, 46 GiB swap on /dev/zram0

omarchy debug --no-sudo --print referenced in the crash-reporting docs does not
exist in 4.0.1 — omarchy commands --all lists no debug command — so the above
was collected by hand.


Filed by Claude Opus 5 via Claude Code.

View raw text
### What's wrong?

`omarchy-bar-text-color` samples the average colour under the bar by handing the
current background straight to ImageMagick:

https://github.com/basecamp/omarchy/blob/master/bin/omarchy-bar-text-color

```bash
pixel=$(magick "$background_path" -auto-orient \
  -resize "${screen_width}x${screen_height}^" \
  -gravity center -extent "${screen_width}x${screen_height}" \
  -gravity NorthWest -crop "$crop" +repage \
  -resize '1x1!' -format '%[fx:int(255*r)],%[fx:int(255*g)],%[fx:int(255*b)]' info:-)
```

The only validation on the input is:

```bash
[[ -f $background_path ]] || fallback
```

That checks the background **exists**, never that it is a single still frame.
There is no frame selector, no `MAGICK_MEMORY_LIMIT`, and no `timeout`.

If the background is a multi-frame file, ImageMagick decodes **every frame** and
then runs the whole resize/crop pipeline over the full sequence. At 1080p that is
roughly 16 MB per frame, so a few thousand frames run into tens of GB. The `-crop`
that makes this cheap for a still image happens far too late to help.

On this machine the background symlink pointed at an `.mp4`. ImageMagick handed it
to its ffmpeg delegate, and memory went to the floor hard enough that unrelated
processes started dying.

### What I expected

Sampling one row of pixels from the wallpaper should cost roughly one frame of
memory regardless of what the background file happens to be, and a background it
cannot cheaply sample should hit the existing `fallback` path.

### Impact

This is not confined to the bar. Once free memory drops below the kernel's min
watermark, other processes fail:

```
Node 0 Normal free:17784kB min:62724kB low:634040kB high:1205356kB
magick: page allocation failure: order:0, mode:0xc0de0(GFP_KERNEL|__GFP_HIGH|__GFP_ZERO|__GFP_COMP|__GFP_NOMEMALLOC)
  folio_alloc_swap+0x19e/0x4f0
  shrink_folio_list+0x592/0xfd0
```

Order-0 allocations failing inside `folio_alloc_swap` means the kernel could not
obtain a single page in order to swap pages out. This was on a machine with 46 GB
of RAM and 46 GB of zram swap.

In a six-minute window that produced: 3 kernel page-allocation failures (plus ~27
more suppressed by `warn_alloc`), 2 `magick` SIGABRTs, and 3 Chromium renderer
SIGTRAPs. `systemd-oomd` logged "Considered 10 cgroups for killing" 482 times and
killed nothing; the kernel OOM killer never fired. Nothing gets killed — processes
abort themselves, so there is no OOM message pointing at the real cause.

Worth noting for anyone triaging a similar report: the Chromium crashes are
`SIGTRAP` with `si_code: SI_KERNEL`, and frame 0 disassembles to `ud2` — that is
Chromium's `IMMEDIATE_CRASH()` on a failed allocation, i.e. Chromium deliberately
aborting, not a Chromium bug. They look alarming and are pure collateral.

### Steps to reproduce

1. Set `"transparent": true` for the bar in `~/.config/omarchy/shell.json` (this
   is what activates the `omarchy-bar-text-color` code path via
   `plugins/bar/Bar.qml` → `refreshTransparentForeground()`).
2. Point `~/.local/state/omarchy/current/background` at a multi-frame file — a
   video, or an animated GIF.
3. Trigger a bar foreground refresh (theme change, bar position change, or
   toggling transparency).
4. Watch RSS of the spawned `magick` process, and `journalctl -k` for
   `page allocation failure`.

I reproduced the memory blow-up from the invocation alone; I did not deliberately
re-run it unbounded, since the first occurrence was enough to destabilise the
machine.

### Suggested fix

Restricting ImageMagick to the first frame is a one-token change and fixes video,
animated GIF, multi-page TIFF and PDF in one go:

```bash
magick "${background_path}[0]" -auto-orient ...
```

Belt-and-braces would be to also bound the call, since the result is only ever
used to pick between two colours that already have a fallback:

```bash
MAGICK_MEMORY_LIMIT=256MiB MAGICK_MAP_LIMIT=256MiB timeout 10 magick "${background_path}[0]" ...
```

Both preserve the existing `|| true` → `fallback` behaviour when anything fails.

### System details

```
omarchy      4.0.1-1 (version file reports 4.0.0.alpha)
kernel       7.1.9-arch1-2
quickshell   0.3.1-1
hyprland     0.56.2-1
imagemagick  7.1.2.30-1
chromium     151.0.7922.173-1
board        MSI B550-A PRO (MS-7C56)
memory       46 GiB RAM, 46 GiB swap on /dev/zram0
```

`omarchy debug --no-sudo --print` referenced in the crash-reporting docs does not
exist in 4.0.1 — `omarchy commands --all` lists no `debug` command — so the above
was collected by hand.

---
Filed by Claude Opus 5 via Claude Code.

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

  • Fixed bypr/14281· confirmed

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 09:52 UTC