Fixing Electron Flatpaks on Fedora 44 (or any distro where X11 access broke)

The Problem

After upgrading to Fedora 44, Electron-based flatpaks (Slack, Signal, Spotify, Mattermost, Telegram, Jitsi, Bruno, Bitwarden, Discord, Postman, Element) and other apps (Flatseal, Flameshot, DBeaver, Zed) stopped working with errors like:

[4:0521/150051.341274:ERROR:ui/ozone/platform/wayland/host/wayland_connection.cc:202]
Failed to connect to Wayland display: Connection refused (111)
[4:0521/150051.341335:ERROR:ui/ozone/platform/wayland/ozone_platform_wayland.cc:281]
Failed to initialize Wayland platform
[4:0521/150051.341428:ERROR:ui/aura/env.cc:246]
The platform failed to initialize.  Exiting.

The apps try Wayland, fail, then don’t fall back to X11.

Users running XFCE (or any X11 session) under GDM are especially affected because GDM reports XDG_SESSION_TYPE=wayland even for X11 sessions, which confuses Electron/Chromium auto-detection.

Root Cause Analysis

Three independent problems conspire to break Electron flatpaks on Fedora 44:

1. GDM lies about the session type

Even when you log into an X11 session (XFCE, etc.), GDM sets XDG_SESSION_TYPE=wayland in the environment. Electron/Chromium use this variable to decide which display protocol to use. When it says "wayland", they try to connect to a Wayland compositor that doesn’t exist.

The session tree on an affected system looks like this:

├─52922 /usr/libexec/gdm-x-session startxfce4
├─52935 /usr/libexec/Xorg vt2 ...
├─53055 xfce4-session

Despite XDG_SESSION_TYPE=wayland, the user is actually running Xorg via gdm-x-session.

2. Flatpak’s fallback-x11 socket doesn’t forward DISPLAY

The Electron base app (org.electronjs.Electron2.BaseApp) uses --socket=fallback-x11 instead of --socket=x11. The fallback-x11 socket does not reliably mount /tmp/.X11-unix/ inside the sandbox, and does not forward the $DISPLAY environment variable. Without DISPLAY and the X11 socket, the app cannot connect to the X server.

The merged permissions for affected apps show:

sockets=fallback-x11;...;wayland;x11;
unset-environment=OZONE_PLATFORM;ELECTRON_OZONE_PLATFORM_HINT;GDK_BACKEND;

The x11 socket is listed, but only because it was explicitly added by a flatpak override. Without the override, only fallback-x11 is present.

The base app also unsets OZONE_PLATFORM, ELECTRON_OZONE_PLATFORM_HINT, and GDK_BACKEND, preventing workarounds via environment variables.

3. Slack’s ELECTRON_ENABLE_WAYLAND=1 prevents X11 fallback

Slack sets ELECTRON_ENABLE_WAYLAND=1 in its flatpak metadata, which forces Electron to prefer Wayland. When Wayland fails, the app exits instead of falling back to X11. Unlike the other apps, environment-based fixes alone don’t help Slack — it needs the --ozone-platform=x11 command-line flag.

The detection path

The detection logic inside Electron/Chromium is roughly:

if (getenv("WAYLAND_DISPLAY"))
    try_wayland();

if (getenv("ELECTRON_ENABLE_WAYLAND"))
    try_wayland();    // ← Slack's code path

if (getenv("OZONE_PLATFORM"))
    use(getenv("OZONE_PLATFORM"));

if (getenv("XDG_SESSION_TYPE") == "wayland")
    try_wayland();    // ← this fires for everyone on Fedora 44

Since OZONE_PLATFORM and GDK_BACKEND are unset by the base app, and XDG_SESSION_TYPE says "wayland", every Electron app tries Wayland first.

The Fix

Step 1: Global override to fix XDG_SESSION_TYPE

cat > ~/.local/share/flatpak/overrides/global << 'EOF'
[Environment]
XDG_SESSION_TYPE=x11
EOF

This tells all flatpaks that the session is X11. Electron/Chromium auto-detection now picks the correct platform.

Do not add sockets=x11 to the global override — it conflicts with some apps (notably Mattermost).

Step 2: Per-app overrides for apps using fallback-x11

# Apps that use fallback-x11 need explicit x11 socket
for app in \
    com.bitwarden.desktop \
    com.discordapp.Discord \
    com.getpostman.Postman \
    com.github.tchx84.Flatseal \
    com.mattermost.Desktop \
    com.slack.Slack \
    com.spotify.Client \
    com.usebruno.Bruno \
    dev.zed.Zed \
    im.riot.Riot \
    io.dbeaver.DBeaverCommunity \
    io.github.ungoogled_software.ungoogled_chromium \
    org.flameshot.Flameshot \
    org.jitsi.jitsi-meet \
    org.signal.Signal \
    org.telegram.desktop; do
    flatpak override --user --socket=x11 "$app"
done

Step 3: Fix Qt apps separately

Telegram (and other Qt-based flatpaks) need an explicit Qt platform plugin:

flatpak override --user --env=QT_QPA_PLATFORM=xcb org.telegram.desktop

Step 4: Slack needs --ozone-platform=x11

Slack has ELECTRON_ENABLE_WAYLAND=1 in its app metadata. This flag is checked before the Ozone auto-detection, so it always tries Wayland first.

Workaround: pass the flag on every invocation:

flatpak run com.slack.Slack --ozone-platform=x11

Add an alias to your shell:

alias slack="flatpak run com.slack.Slack --ozone-platform=x11"

Or create a desktop file override so the app menu works:

cp -p /var/lib/flatpak/exports/share/applications/com.slack.Slack.desktop \
   ~/.local/share/applications/com.slack.Slack.desktop
# Edit Exec line to add --ozone-platform=x11

The resulting Exec line should be:

Exec=/usr/bin/flatpak run --branch=stable --arch=x86_64 \
  --command=com.slack.Slack --file-forwarding \
  com.slack.Slack --ozone-platform=x11 @@u %U @@

How to reproduce

Anyone with the following setup can reproduce this:

  • Fedora 44 (or any distro with Flatpak 1.17.x and GDM)

  • X11 session (XFCE, i3, MATE, etc.) logged in via GDM

  • Electron-based flatpak installed (Slack, Signal, Mattermost, etc.)

Run any Electron flatpak:

flatpak run org.signal.Signal
# → ERROR: Failed to connect to Wayland display: Connection refused
# → ERROR: The platform failed to initialize.  Exiting.

Check the session type:

echo $XDG_SESSION_TYPE
# → "wayland"  ← even though you're on X11!
loginctl session-status
# → Type: wayland  ← GDM lies

Check which socket the app uses:

flatpak info --show-permissions org.signal.Signal
# → sockets=fallback-x11;...;wayland;
# → unset-environment=OZONE_PLATFORM;...;GDK_BACKEND;

Verification

After applying the fixes, verify with:

# Check that DISPLAY and X11 socket are available inside each sandbox
flatpak run --command=bash org.signal.Signal -c \
  'echo "DISPLAY=$DISPLAY"; ls /tmp/.X11-unix/X0'
# → DISPLAY=:0.0
# → /tmp/.X11-unix/X0

# Launch the actual app
flatpak run org.signal.Signal
# → Window "Signal" appears

Summary of commands applied

# 1. Global: fix session type
cat > ~/.local/share/flatpak/overrides/global << 'EOF'
[Environment]
XDG_SESSION_TYPE=x11
EOF

# 2. Per-app: add x11 socket for ALL apps using fallback-x11
for app in \
    com.bitwarden.desktop \
    com.discordapp.Discord \
    com.getpostman.Postman \
    com.github.tchx84.Flatseal \
    com.mattermost.Desktop \
    com.slack.Slack \
    com.spotify.Client \
    com.usebruno.Bruno \
    dev.zed.Zed \
    im.riot.Riot \
    io.dbeaver.DBeaverCommunity \
    io.github.ungoogled_software.ungoogled_chromium \
    org.flameshot.Flameshot \
    org.jitsi.jitsi-meet \
    org.signal.Signal \
    org.telegram.desktop; do
    flatpak override --user --socket=x11 "$app"
done

# 3. Qt apps: set platform to xcb
flatpak override --user --env=QT_QPA_PLATFORM=xcb org.telegram.desktop

# 4. Slack: alias or desktop file with --ozone-platform=x11
alias slack='flatpak run com.slack.Slack --ozone-platform=x11'

What doesn’t work

Some things we tried that didn’t fix the issue:

  • Setting GDK_BACKEND=x11 or OZONE_PLATFORM=x11 via override — the base app’s unset-environment clears them

  • Setting WAYLAND_DISPLAY= (empty) — already done by the base app

  • Using fallback-x11 instead of x11 — doesn’t mount the socket

  • A global sockets=x11 override — conflicts with Mattermost

Why this happens specifically on Fedora 44

Fedora 44 ships Flatpak 1.17.7 (development branch). This version appears to have changed how the fallback-x11 socket works. On earlier Fedora releases with Flatpak 1.14.x / 1.15.x, fallback-x11 properly forwarded $DISPLAY and mounted /tmp/.X11-unix/. The regression is in how Flatpak 1.17.x handles this socket type.

Additionally, Fedora 44’s GDM configuration always sets XDG_SESSION_TYPE=wayland regardless of the actual session type, breaking any app that relies on this variable for display server detection.

Categories: development 
Tags: sysadm 

See also