Tiling managers are not destroyed in disable(), so window-created handlers keep running (Gio.Settings constructed without schema)

Open Beginner friendly
#641 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 3 days

@gnacho is already working on this.

Since Nov 7, 2026.

  • #642 by @gnacho — open

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript
Domain
desktop

Research direction

Read src/extension.ts and src/settings/settings.ts, focusing on disable(), TilingManager.destroy(), and the gioSetting getter. Check how manager signals are connected and disconnected, then reproduce by disabling the extension and creating a window. Done means no Tiling Shell handler reacts while disabled and no Gio.Settings schema exception is logged.

Written by the indexing model from the issue text.

Description

Describe the bug

Every window created while Tiling Shell is disabled logs a JS exception, because the tiling managers are never destroyed in disable() and their window-created handler keeps running after Settings.destroy() has nulled the settings object.

JS ERROR: Error: One of property 'schema-id' or 'settings-schema' are required for Gio.Settings
_init@resource:///org/gnome/gjs/modules/core/overrides/Gio.js:832:23
get gioSetting@.../settings/settings.js:147:30
get_boolean@.../settings/settings.js:28:3
get ENABLE_AUTO_TILING@.../settings/settings.js:316:12
enable/<@.../components/tilingsystem/tilingManager.js:251:13
@resource:///org/gnome/shell/ui/init.js:20:20

To Reproduce

  1. Tiling Shell 18.0 (99) on GNOME Shell 51.1, Wayland.
  2. gnome-extensions disable [email protected]
  3. Open any window, for example gnome-calculator.
  4. The exception above is logged immediately (4 lines in my test).

It also happens without disabling the extension by hand: it has no session-modes, so GNOME disables it on every screen lock and re-enables it on unlock. I get 2 exceptions per lock cycle, 340 in 11 days of uptime.

Root cause

Two independent problems, both in main:

  1. disable() (src/extension.ts) never destroys this._tilingManagers. Each TilingManager connects to global.display window-created in enable(), and only TilingManager.destroy() disconnects those signals. After disable(), the handlers stay connected to a live display.
  2. disable() calls Settings.destroy(), which sets _settings = null, and the getter falls back to new Gio.Settings() without a schema (src/settings/settings.ts:168). Any read after that point throws.

So the sequence is: extension disabled, window created, stale handler runs, Settings.ENABLE_AUTO_TILING, new Gio.Settings(), exception.

_createTilingManagers() already destroys and recreates the managers on enable(), so destroying them in disable() is consistent with the existing lifecycle.

Expected behavior

No JS exception when a window is created while the extension is disabled, and no Tiling Shell code reacting to windows while disabled.

Proposed fix

// src/extension.ts, disable(), before Settings.destroy()
this._tilingManagers.forEach((tm) => tm.destroy());
this._tilingManagers = [];

// src/settings/settings.ts
static get gioSetting(): Gio.Settings {
    return this._settings ?? new Gio.Settings({ schema_id: 'org.gnome.shell.extensions.tilingshell' });
}

Environment

  • Tiling Shell 18.0 (99), installed from extensions.gnome.org
  • GNOME Shell 51.1, mutter 51.1, Wayland
  • Arch / CachyOS, AMD Radeon 890M
  • Schema is correctly compiled and present (schemas/gschemas.compiled), so this is not the manual-ZIP issue from #613

Related

  • #633 is the same lock/unlock lifecycle leaking a different object (KeyBindings).
  • #559 touches the teardown order in disable().

I have the fix working locally and can open a PR if you want it.

Dominant language
TypeScript
Stars
2.1k
Forks
138
Avg merge
5d 8h
Merged PRs (30d)
3

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from domferr/tilingshell

All issues in domferr/tilingshell

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.