Monitor layout lost after Quattro: monitors.conf replaced by monitors.lua
After the Omarchy 4 Quattro upgrade your monitors.conf is ignored and monitors.lua holds stock defaults. Port each monitor line to hl.monitor by hand.
Your old ~/.config/hypr/monitors.conf is still on disk but Omarchy 4 never reads it. Open ~/.config/hypr/monitors.lua (Setup > Monitors in the menu) and rewrite each old monitor= line as an hl.monitor table, and each env = GDK_SCALE line as hl.env. Save, then run hyprctl reload. Nothing ports it for you, on any 4.0.x release.
You upgraded to Omarchy 4 and your screens came back in the wrong order, the wrong rotation, or at the wrong scale. Your old ~/.config/hypr/monitors.conf is still sitting there. Omarchy 4 never reads it.
The fix
Checked on 4.0.4. The same steps apply to every 4.0.x release, because nothing in 4.0.1 through 4.0.4 changed this.
-
Look at what you had.
cat ~/.config/hypr/monitors.conf. The file survives the upgrade unchanged, so your old layout is still readable. The upgrade makes no backup of it, so if it is gone, something other than Omarchy removed it. -
Open the new file. Use Setup > Monitors in the Omarchy menu, or run
omarchy launch config-editor ~/.config/hypr/monitors.lua. -
Translate each line. The Lua form takes one table per output:
-- monitor=,preferred,auto,auto hl.monitor({ output = "", mode = "preferred", position = "auto", scale = "auto" }) -- monitor = DP-2, 2560x1440@165, 1920x0, 1 hl.monitor({ output = "DP-2", mode = "2560x1440@165", position = "1920x0", scale = 1 }) -- monitor = DP-2, preferred, auto, 1, transform, 1 hl.monitor({ output = "DP-2", mode = "preferred", position = "auto", scale = 1, transform = 1 }) -- monitor=DP-2,disable hl.monitor({ output = "DP-2", disabled = true })Positional arguments become named keys. Extra 3.x flags that used to trail the line, such as
transformandvrr, become keys in the same table. Numbers stay unquoted, strings get quotes, andscale = "auto"is a quoted string because it is not a number.mirror = "eDP-1"is the mirroring key, which is whatomarchy-hyprland-monitor-internal-mirrorwrites. -
Match monitors by description if you have identical panels.
output = "desc:Hewlett Packard HP Z27i CNK4040DPF"works the same as it did in 3.x. Get the strings fromhyprctl monitors all. -
Port your GTK scale. The old
env = GDK_SCALE,1becomeshl.env("GDK_SCALE", "1"). The shipped template sets this through two variables at the top of the file, and ships them at the 2x retina defaults:local omarchy_gdk_scale = 2 local omarchy_monitor_scale = "auto" hl.env("GDK_SCALE", tostring(omarchy_gdk_scale)) hl.monitor({ output = "", mode = "preferred", position = "auto", scale = omarchy_monitor_scale })If you run one scale for everything, keep that shape and just change the two numbers, for example
1and1for a 1080p or 1440p desk. TheSuper + /scaling hotkeys write back into those two variables, so editing them is the supported path. -
Reload. Save the file and Hyprland picks it up on its own config reload. If you want to force it, run
hyprctl reload. -
Delete or rename
monitors.confonce the new file works, so you do not edit the dead one by mistake six months from now.
Verify it worked
Run hyprctl monitors all and read back scale, transform, at and description for each output. They should match what you wrote.
Then log out and back in. This catches the case where a value applies live but not at startup, which is the shape of issue #7066, where a transform value survives in the file but the rotation is not applied after a restart until the value is changed and changed back.
Also press Super + Return. If no keybinding responds, your Lua did not parse. See below.
Why it happens
Omarchy 4 moved the whole Hyprland configuration from .conf to Lua. ~/.config/hypr/hyprland.lua is the entry point and it pulls in your overrides with require("hypr.monitors"), which resolves to monitors.lua. There is no keyword parser left to read a .conf file.
The upgrade script omarchy-upgrade-to-quattro keeps a list it calls always_copy_config_files, and hypr/monitors.lua is on it. Those files are treated as new Quattro entry points that no older install could have, so the stock template is copied in unconditionally. The stock template is a single catch-all rule with position = "auto", scale = "auto", and omarchy_gdk_scale = 2.
monitors.conf is not on the retire list, so it is neither backed up nor removed. That is the whole bug. daventhedude documented this in issue #6911: the old file stays on disk, nothing renames it, and the upgrade summary never mentions it, so you get no hint that your display settings stopped applying. Their three-monitor setup came up with a portrait panel in landscape, wrong positions, and GTK apps at 2x on 1440p.
That issue was still open on 2026-09-16. The filename monitors.conf does not appear anywhere in the 4.0.4 tree, not in the upgrade script and not in any migration. The only attention the old ~/.config/hypr/*.conf files get is a temporary shim the upgrade script builds so the still-running 3.x session does not break on reload mid-upgrade. Nothing reads them afterwards.
If that did not work
Nothing responds to the keyboard after you edit the file. A syntax error or runtime error in monitors.lua aborts the Lua thread before require("hypr.bindings") runs, so the desktop starts with a wallpaper and a bar but no shortcuts at all. codyoss filed this as #9721, still open. Get a TTY with Ctrl + Alt + F2, fix the file, or restore the shipped default with omarchy-refresh-config hypr/monitors.lua, which backs your version up first.
A scale change snaps back within a second or two. This is the known interaction between explicit per-output rules and the scaling tool. omarchy-hyprland-monitor-scaling applies the new scale live with hyprctl eval, then persists it by rewriting only the omarchy_monitor_scale variable or the wildcard output = "" rule. With explicit hl.monitor({ output = "eDP-1", ... }) rules in the file, that goes wrong in one of two ways. If you kept the stock catch-all above your rules, the variable does get rewritten, but the file write triggers a config reload and your explicit rule overrides the catch-all again, which is what Douda traced in #7242. If you removed the catch-all, the sed finds nothing to rewrite and silently no-ops, and on a laptop with an external screen the clamshell poller re-applies the file value every couple of seconds, which RonRayReed traced in #8103 using ~/.local/state/omarchy/monitor-scaling.log. Either way the fix is the one RonRayReed gives: edit the scale in the explicit rule and reload, rather than using the Display panel or the hotkey. Both issues were still open on 2026-09-16.
Your cursor gets stuck between two screens. If you ported absolute positions like 1920x0 and then changed a scale, the logical size of that output shrank and left a dead zone. syskey8 wrote this up in discussion #8213 and proposed relative positions such as position = "auto-right" in PR #8362. That PR was still open and unmerged on 2026-09-16, and the 4.0.4 template still ships position = "auto", so you have to make this change yourself.
You are copying a 3.x guide that says hyprctl keyword monitor .... That call is rejected under the Lua parser with keyword can't work with non-legacy parsers. Use hyprctl eval with an hl.monitor({ ... }) call instead, which is what the Omarchy monitor scripts do.
Related
The manual chapter on monitors covers scaling values and the clamshell behaviour on 4.x. For the same silent replacement applied to your shortcuts, see custom keybindings lost after Quattro. For layouts that refuse to stick across reboots or docking, see multi-monitor layout not saved and multi-monitor. For apps that came back huge or blurry after the GDK_SCALE default changed, see fractional scaling blurry or huge apps. The broader port is covered in Hyprland conf to Lua migration and 3 to 4 Quattro.
Upstream threads about this error
76 issues on the Omarchy tracker match this error cluster. Newest fixes often appear as comments on the most-discussed threads.
| Issue | State | Comments | Opened |
|---|---|---|---|
| #6909 [Quattro] eDP-1 monitor scaling forces 2x reset on mixed-monitor array with Quickshell navbar · fixed by #7581 | closed | 13 | 2026-08-14 |
| #8113 Omarchy unusable under VMware Workstation with 3D acceleration enabled | closed | 10 | 2026-08-24 |
| #7025 omarchy-menu-keybindings hangs forever when a user Lua config iterates hl.get_monitors() | open | 9 | 2026-08-15 |
| #12083 4K@120 HDMI screen blanks for seconds on every new frame after linux-omarchy 7.2.5-3 (AMD Navi 33) | open | 9 | 2026-09-16 |
| #6673 [Quattro] Display panel scale is per-monitor at runtime but persists globally, rescaling other monitors on reload · fixed by #5 | open | 3 | 2026-08-10 |
| #7084 Clamshell watcher ignores desc: rules for the internal panel and overwrites its scale every 2s | open | 4 | 2026-08-16 |
| #7242 omarchy hyprland monitor scaling reverts instantly when monitors.lua has per-monitor rules · fixed by #5 | closed | 4 | 2026-08-17 |
| #7326 Internal monitor position cannot be made to stick: clamshell watcher and Display panel scaling both re-apply position = "auto" | open | 4 | 2026-08-17 |
| #8103 omarchy-hyprland-monitor-scaling doesn't persist scale on outputs with explicit per-monitor rules in monitors.lua | closed | 4 | 2026-08-24 |
| #9804 Quickshell crashes with SIGSEGV in QSGRenderThread when Hyprland monitor is set to 10-bit (bitdepth = 10) | open | 4 | 2026-09-02 |
Accepted answers upstream
- Feature Request: Out-of-the-box DisplayLink support · answered by lordyoyi
- Update monitor configuration defaults and docs to use relative positioning (auto) to prevent cursor trapping · answered by syskey8
- Relative display placement and rotation in the Display panel (an alternative to drag-and-drop) · answered by Azteriisk
- Unified GUI Settings Panel + Wi-Fi throughput bug (RTL8821CE) · answered by e2jk
Questions people ask
- Does the Quattro upgrade delete my monitors.conf?
- No. It leaves the file in ~/.config/hypr/ untouched and simply stops reading it. It gets no .bak rename and no mention in the upgrade output, which is why the loss is silent. The reporter of #6911 noted that other configs on their 4.0.0 upgrade did get parked as .bak files, which is what made the omission stand out.
- Can I just symlink monitors.conf back in?
- No. Omarchy 4 starts Hyprland from hyprland.lua, which requires hypr.monitors as a Lua module. The old keyword parser is not loaded, so a .conf file has nothing to parse it.
- Is there a tool that converts the file for me?
- Not in Omarchy as of 4.0.4. No migration shipped through 4.0.4 touches monitors.conf, and the filename does not appear anywhere in the 4.0.4 source tree. Porting the lines by hand is the only path.
Sources and credit
Fixes on this page were worked out by daventhedude (Traced the upgrade path and published a working three-monitor monitors.lua), Douda (Isolated why a scale change reverts when an explicit per-output rule exists), RonRayReed (Traced the clamshell watcher re-applying the stale scale from monitors.lua), syskey8 (Explained the cursor dead zone from absolute positions under fractional scaling). Text here is our own paraphrase; follow the links for the original threads.
- issueIssue #6911: Quattro upgrade replaces customized monitors.conf with default monitors.lua (auto layout, GDK_SCALE=2) without porting or warning · daventhedude · 2026-08-15
- issueIssue #7242: omarchy hyprland monitor scaling reverts instantly when monitors.lua has per-monitor rules · Douda · 2026-08-17
- issueIssue #8103: omarchy-hyprland-monitor-scaling doesn't persist scale on outputs with explicit per-monitor rules in monitors.lua · RonRayReed · 2026-08-24
- issueIssue #7066: Omarchy Quatro: Not Honoring Transform in Monitor Config · YuseiRun · 2026-08-16
- issueIssue #9721: hyprland.lua: Sub-module require errors abort script evaluation before hypr.bindings, locking user out of keybindings · codyoss · 2026-09-02
- discussionDiscussion #8213: Update monitor configuration defaults and docs to use relative positioning (auto) to prevent cursor trapping · syskey8 · 2026-08-25
- prPR #8362: Fix: Use relative positioning (auto-right) in multi-monitor defaults to prevent scaling cursor traps · syskey8 · 2026-08-26
- manualOmarchy manual: Monitors