Skip to content

fix: handle nirilayout.kdl as a regular file (noctalia 5)#2

Open
Piero-93 wants to merge 2 commits into
calico32:mainfrom
Piero-93:fix/noctalia5-regular-file
Open

fix: handle nirilayout.kdl as a regular file (noctalia 5)#2
Piero-93 wants to merge 2 commits into
calico32:mainfrom
Piero-93:fix/noctalia5-regular-file

Conversation

@Piero-93

Copy link
Copy Markdown

fix: crash on startup when nirilayout.kdl is a regular file (noctalia 5)

Problem

nirilayout crashes on startup with a nil pointer dereference for users on
noctalia 5:

panic: runtime error: invalid memory address or nil pointer dereference
...
gtk/v4.(*FlowBox).Insert(...)
nirilayout.Run(...) nirilayout.go:123

noctalia 5 writes ~/.config/niri/nirilayout.kdl as a regular file
(a copy of the active layout) instead of a symlink to it. os.Readlink
then fails with EINVAL, but only fs.ErrNotExist was handled, so the error
was propagated as fatal to Run. The FlowBox was never created (selector
stayed nil) while the layout loop still ran, dereferencing the nil selector.

Fix

  • Add CurrentLayoutPath, which resolves the symlink when present (classic
    setup) and otherwise matches the file's contents against the known layout
    files (noctalia 5). Active-layout preselection now works in both setups,
    with no command-line flag.
  • Stop treating current-layout detection as a fatal error (it only affects
    which layout is preselected).
  • Guard the layout loop against a nil selector as defense in depth.

Testing

  • go build ./... and go test ./... pass.
  • Reproduced the original crash with a regular-file nirilayout.kdl; the
    rebuilt binary no longer crashes and shows the layout list.
  • Verified the active layout is still highlighted with both a symlink and a
    regular-file nirilayout.kdl.
  • Working on both shells.

Piero-93 added 2 commits July 9, 2026 22:02
noctalia 5 writes ~/.config/niri/nirilayout.kdl as a regular file instead
of a symlink to the active layout. os.Readlink then fails with EINVAL,
which was only handled for ErrNotExist, so the error was treated as fatal:
the FlowBox was never created while the layout loop still ran, dereferencing
a nil selector and crashing with a nil pointer at Run.

Detect the active layout via a new CurrentLayoutPath helper, which resolves
the symlink when present (classic setup) and otherwise matches the file's
contents against the known layouts (noctalia 5). Current-layout preselection
now works in both setups, with no command-line flag needed.

Also stop treating current-layout detection as fatal, and guard the layout
loop against a nil selector.
SetCurrentLayout used to replace nirilayout.kdl with a symlink to the
active layout file. Setups that manage nirilayout.kdl as a regular file
(e.g. noctalia) never followed that symlink swap, so switching layouts
had no effect even though the switcher still showed the correct current
layout.

Write the selected layout's contents into nirilayout.kdl directly instead,
still atomically via a temp file + rename (and remove the temp file if the
rename fails). niri's `include` reads the contents either way, so this works
for every setup: the classic symlink setup, noctalia 4 and noctalia 5.

Also update the now-stale CurrentLayoutPath comment: it still tries Readlink
first for backward compatibility with symlinks left by older versions, but
new writes are always regular files.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant