Hyprland Freezes Randomly Under Load – How I Traced It to One Misbehaving Wayland App Using Debug Logging
Hyprland Freezes Randomly Under Load – How I Traced It to One Misbehaving Wayland App Using Debug Logging
It starts as a whisper. A skipped frame. A half-second of hesitation in the middle of a full-screen YouTube video. Then, one day, it becomes a shout: your entire Hyprland session, your beautiful, tiling, fluid masterpiece, freezes solid. The mouse is a tombstone. The keyboard, a brick. All you can do is hold the power button and pray your work survives the reboot.
For weeks, I lived with this ghost in my machine. My Hyprland setup on Arch Linux—usually a symphony of swaying windows and keyboard-driven elegance—would randomly seize up, always under load, always when I was most in flow. I blamed the kernel, the Nvidia drivers (the usual suspect), the compositor itself. But the truth, as I discovered, was a single, misbehaving Wayland application. And I found it not by guesswork, but by learning to listen to Hyprland's own voice.
This is the story of that hunt. If your Hyprland freezes randomly, especially under GPU or memory load, this guide might just be your roadmap to stability.
The Short Answer: How I Fixed It (The "Useful Info First")
The Problem: My Hyprland compositor would completely freeze (hard lock) for 30+ seconds, or indefinitely, when I had multiple apps running, especially a browser with video, a code editor, and a terminal.
The Root Cause: A single Wayland-native application was causing a fatal stall in the Wayland event loop. It wasn't a crash; it was a block. The entire compositor waited for this one app to respond, and it never did.
The Diagnostic Tool: Hyprland's built-in debug logging, enabled via the HYPRLAND_LOG_LEVEL environment variable and monitored in real-time with journalctl.
The Fix: I identified the offending app (in my case, a niche status bar widget) by:
- Enabling
HYPRLAND_LOG_LEVEL=TRACE - Recreating the freeze while logging
- Scouring the logs for the last repetitive message before the silence.
- Isolating and killing the guilty process (
pkill -f [offending_app_name]) restored Hyprland instantly, confirming the culprit. - Permanently removing or replacing that application.
If you want to skip the story and try this now:
# 1. From a TTY (Ctrl+Alt+F2) or before the freeze, open a terminal and run:
HYPRLAND_LOG_LEVEL=TRACE Hyprland &> ~/hyprland_crash.log &
# Or launch it from your display manager script with this env variable.
# 2. When the freeze happens, switch to a TTY (Ctrl+Alt+F2), log in.
# 3. Check the last lines of the log:
tail -f ~/hyprland_crash.log
# Or use journalctl to see Hyprland's journal:
journalctl -f -t Hyprland
# 4. Look for repeating warnings/errors about a specific client, surface, or event.
# 5. Kill the suspected app's process.
Now, let's dive into the why and the how, so you can apply this methodology to any freeze you encounter.
Understanding the Ghost: Why Wayland Freezes Feel Different
On X11, a misbehaving app might crash, slow down, or cause visual glitches. On Wayland, and especially with a compositor like Hyprland that tightly integrates the display server and window manager, a client app that locks up its side of the Wayland protocol can lock up everything.
Think of Hyprland as a maestro conducting an orchestra. Each application is a musician. The protocol (Wayland) is the sheet music. If one violinist (app) stops reading the music, stares blankly, and refuses to proceed, the maestro (Hyprland) has a choice: stop the entire orchestra and wait, or fire the violinist. Hyprland, by design, tends to wait—hoping for a response to complete a critical transaction. This wait is your freeze.
Why this is different from X11: On X11, the display server (Xorg) is separate from the window manager. A frozen app doesn't freeze the compositor because Xorg can continue managing other clients independently. On Wayland, the compositor is the display server. If it's waiting for a client response during a critical rendering operation, everything stops.
The Wayland protocol and blocking: The Wayland protocol uses a request-response model for certain operations. When a client needs to commit a new frame buffer, it must coordinate with the compositor. If the client stops responding during this handshake, the compositor may block waiting for the response. This is by design—it prevents rendering artifacts and tearing—but it means a single misbehaving client can freeze the entire desktop.
Common types of Wayland freezes:
- Buffer commit stalls: A client takes too long to provide the next frame buffer.
- Shared memory exhaustion: A client allocates too much shared memory for Wayland buffers, causing the compositor to stall.
- File descriptor leaks: A client opens too many file descriptors (for buffers, pipes, etc.) without closing them, eventually exhausting the system limit.
- GPU memory pressure: Multiple GPU-accelerated apps compete for VRAM, causing the compositor to stall while waiting for GPU resources.
The Deep Dive: My Step-by-Step Forensic Process
Phase 1: Replication & Observation
First, I had to find a pattern. The freeze seemed tied to load, but not purely CPU or RAM. It was often graphical load: switching workspaces with animations while a video played, or resizing a GPU-accelerated IDE window. This pointed to the GPU or the Wayland protocol messaging around buffers and frames.
I started a detective's notebook:
- Time of freeze
- Open applications
- Recent action (e.g., "switched to workspace with Firefox playing Twitch").
- Could I switch to a TTY (Ctrl+Alt+F2)? (Yes, which meant the kernel was fine—this was crucial information.)
The TTY test is critical. If you can switch to a TTY while the desktop is frozen, it tells you:
- The kernel is running (not a kernel panic)
- The GPU is partially responsive (TTY switching requires some GPU functionality)
- The problem is at the compositor level, not the hardware level
- You can still use the TTY to diagnose and fix the issue without a hard reboot
If you cannot switch to a TTY, the issue is more serious—possibly a GPU hang or kernel issue. In that case, try the SysRq magic keys: Alt+SysRq+R (unraw keyboard), then Alt+SysRq+E (send SIGTERM to all processes), then Alt+SysRq+I (send SIGKILL). This can sometimes recover a completely frozen system.
Phase 2: Enabling the Debug Logs – Listening to the Maestro
This is the crucial step. Hyprland speaks, loudly and clearly, if you ask it to. You must launch it with debug logging enabled.
Method 1: Launching from a TTY (Most Reliable)
If you can predict a freeze, or are about to trigger it:
- Switch to a TTY with
Ctrl+Alt+F2. Log in. - Kill your current session (if needed) with
killall Hyprland. - Launch with tracing:
This will output everything to your terminal. Let it run, switch back to your session (HYPRLAND_LOG_LEVEL=TRACE HyprlandCtrl+Alt+F7), and do what causes the freeze. When it freezes, switch back to the TTY (Ctrl+Alt+F2) and see the last messages.
Method 2: Logging to a File & Journalctl
I prefer this as it's persistent and doesn't require switching away from the GUI:
# Edit your Hyprland start command (in ~/.zprofile or your display manager config)
export HYPRLAND_LOG_LEVEL=WARN # Or TRACE for extreme verbosity
exec Hyprland > /tmp/hyprland.log 2>&1
Then, when a freeze happens, jump to a TTY and run tail -f /tmp/hyprland.log. Even better, Hyprland logs to the systemd journal. From a TTY, run:
journalctl -f -t Hyprland
The -f (follow) flag will show you the last messages as they arrived before the stall.
Method 3: Runtime Log Level Change (Hyprland 0.40+)
Newer versions of Hyprland allow you to change the log level at runtime using hyprctl:
# From a TTY while Hyprland is frozen
hyprctl setoption log_level TRACE
This is extremely useful for catching freezes that you can't predict.
Understanding log levels:
TRACE: Everything. Extremely verbose. Use only when actively hunting.DEBUG: Detailed debug information. Good for general debugging.WARN: Warnings and errors only. Best for daily use—catches problems without overwhelming you with output.CRIT: Only critical errors. Too quiet for debugging freezes.
For daily use, I recommend setting HYPRLAND_LOG_LEVEL=WARN in your startup script. Switch to TRACE only when actively debugging. This gives you a historical record of warnings that might help you identify patterns before the next freeze.
Phase 3: Reading the Tea Leaves – Interpreting the Logs
You don't need to understand every line. You're looking for anomalies just before the log output stops. Here's what I looked for:
- Repetitive Error/Warning Lines: A loop of the same error. In my case, it was a stream of warnings about a "buffer commit" from a specific
wl_surfaceID. - The Last Client Mentioned: Hyprland often logs messages like
[src/events/Layers.cpp:123] layerSurface .... Note the surface or client ID. - Context: The logs just before the freeze were all about a single workspace or a specific layer (like a waybar or eww widget).
- Memory allocation failures: Lines containing "failed to allocate" or "out of memory" indicate resource exhaustion.
- Timeout messages: Lines mentioning "timed out" or "took too long" directly point to the stalling component.
The smoking gun was a series of lines like:
[WARN] [src/...] client [id] took too long to commit buffer, stalling...
[WARN] [src/...] client [id] took too long to commit buffer, stalling...
[WARN] [src/...] client [id] took too long to commit buffer, stalling...
And then—silence.
Log analysis tips:
# From a TTY, search for the last warnings before the freeze
journalctl -t Hyprland --since "5 minutes ago" | grep -i "warn\|error\|stall\|timeout"
# Find the most frequently logged message (the repeating pattern)
journalctl -t Hyprland --since "10 minutes ago" | sort | uniq -c | sort -rn | head -20
# Look for buffer-related messages
journalctl -t Hyprland --since "5 minutes ago" | grep -i "buffer\|commit\|surface"
Phase 4: The Identification and Kill Shot
Hyprland's logs include PID (Process ID) or app IDs sometimes. You can cross-reference. I used hyprctl clients from a TTY after a freeze (while Hyprland was still frozen) to list all clients. I looked for the "last active" or ones matching the suspicious window class.
# From a TTY while Hyprland is frozen
hyprctl clients
# This will show all running clients with their:
# - Window class
# - Title
# - PID
# - Workspace
# - Floating/tiled state
The definitive test: Force-kill a suspect. From the TTY:
pkill -f "eww" # I suspected my eww widget
Within a second of that command, my Hyprland session—still frozen on the other TTY—sprung back to life! The maestro had fired the violinist, and the orchestra could play again.
Systematic elimination: If you're not sure which app is causing the freeze, you can eliminate them one by one:
# List processes sorted by CPU/memory usage (likely culprits)
ps aux --sort=-%mem | head -20
ps aux --sort=-%cpu | head -20
# Kill the most suspicious one
kill
# If the desktop unfreezes, you found it
# If not, try the next one
Important: Always use kill (SIGTERM) first, not kill -9 (SIGKILL). SIGTERM gives the process a chance to clean up. SIGKILL is a last resort and can leave resources (like shared memory segments) in an inconsistent state.
Phase 5: The Permanent Fix
The offending app (for me, a custom eww widget that did GPU-heavy rendering) was irredeemable. I:
- Removed it from my config.
- Replaced its functionality with a lighter tool (waybar).
- Added a failsafe keybind in
hyprland.confto kill it if needed:bind = SUPER SHIFT, E, exec, pkill -f eww
General principles for permanent fixes:
- Replace the offending app with a lighter alternative. If it's a status bar, try
waybarinstead ofeww. If it's a terminal, tryfootinstead ofkittyfor GPU-lightweight operation. - Report the bug. If the app is actively maintained, file a bug report with the log excerpt showing the stall. Developers need these logs to fix the underlying issue.
- Pin the version. If an update introduced the freeze, pin the previous working version until the bug is fixed.
- Add a kill keybind. Create a Hyprland keybind that kills the most likely offender, so you can recover from a freeze without switching to a TTY:
# Emergency kill binds bind = SUPER ALT, Q, exec, pkill -f "problematic-app" bind = SUPER ALT, Escape, exec, killall -9 Hyprland # Nuclear option: restart Hyprland
Advanced Diagnostics: When the Basic Approach Isn't Enough
Monitoring GPU Memory
If you suspect GPU memory pressure is causing the freeze:
# For NVIDIA
nvidia-smi
# For AMD
radeontop
# For Intel
intel_gpu_top
# General GPU memory info
cat /sys/class/drm/card0/device/mem_info_vram_total 2>/dev/null
cat /sys/class/drm/card0/device/mem_info_vram_used 2>/dev/null
If GPU memory is near capacity, closing GPU-heavy apps (browsers, games, GPU-accelerated terminals) can prevent freezes.
Checking File Descriptor Limits
A process leaking file descriptors can eventually cause the compositor to stall:
# Check the file descriptor count for a process
ls /proc//fd | wc -l
# Check system-wide limits
cat /proc/sys/fs/file-nr
# Increase limits if needed (temporary)
sudo sysctl -w fs.file-max=1000000
Using perf for Deeper Profiling
For truly mysterious freezes, Linux's perf tool can reveal what the Hyprland process is doing when it stalls:
# From a TTY while Hyprland is frozen
sudo perf top -p $(pgrep Hyprland | head -1)
# Or record for later analysis
sudo perf record -p $(pgrep Hyprland | head -1) -g -- sleep 5
sudo perf report
This shows you exactly which function Hyprland is stuck in, which can pinpoint whether the issue is in the renderer, the Wayland protocol handler, or a driver call.
Common Culprits and Their Fixes
Based on community reports and my own experience, here are the apps most likely to cause Hyprland freezes:
| App | Why It Freezes | Fix |
|---|---|---|
| eww widgets | GPU-heavy rendering in layer shell | Replace with waybar |
| waybar (certain configs) | Custom CSS animations, too many modules | Simplify config, reduce modules |
| Discord (Flatpak) | Buffer commit stalls, GPU process hangs | Use --ozone-platform=x11 |
| Firefox (with video) | GPU process crashes under load | Disable hardware acceleration or use MOZ_DISABLE_RDD_SANDBOX=1 |
| OBS Studio | GPU capture pipeline stalls | Use PipeWire capture instead of XSHM |
| Kitty terminal | GPU renderer conflict | Switch to foot or use kitty --disable-ligatures |
| Games (Proton/Wine) | Fullscreen GPU takeover | Use gamescope as a compatibility layer |
Lessons for a Stable Hyprland Setup
- Suspect Wayland-Native Apps First: Electron apps, custom widgets (
eww,nwg-panel), screen recorders, and clipboard managers are common culprits. Test by running without them for a day. - The TTY is Your Lifeline: Knowing you can switch to a TTY (
Ctrl+Alt+F2) eliminates hardware/driver panic. It means the problem is at the compositor level and is fixable. - Logs Are Your Best Friend:
HYPRLAND_LOG_LEVEL=WARNis a good default for your startup.TRACEis for active hunting. Never run without some level of logging. - Update Relentlessly: Hyprland and its plugins (
hyprpm) update fast. Bugs are fixed constantly. Check for updates weekly:sudo pacman -Syu hyprland(Arch) or build from source for the latest fixes. - Community Wisdom: The Hyprland GitHub issues and Discord are goldmines. Search for "freeze" and your app names. Chances are someone has already encountered and solved your exact issue.
- Create Emergency Keybinds: Have a keybind that can kill Hyprland or the likely offender without needing a TTY. This saves precious seconds during a freeze.
- Monitor Resource Usage: Install
btoporhtopand keep it running in a workspace. Watch for memory leaks or CPU spikes that precede freezes.
Final Thought: Embrace the Hunt
The beauty of open-source, of Hyprland, of this entire Linux journey, is transparency. The system is not a black box. It wants to tell you what's wrong. You just have to learn its language. My random freezes weren't a curse; they were a puzzle. And solving that puzzle didn't just fix my computer—it deepened my relationship with the tool I use every day.
So, if your Hyprland is freezing, don't just reboot. Listen. Log. Isolate. You'll find your ghost, and your desktop will be faster and more stable for the hunt.
Quick Reference: Hyprland Freeze Debug Checklist
- Can you switch to a TTY? (Ctrl+Alt+F2) — If yes, it's compositor-level
- Enable debug logging:
HYPRLAND_LOG_LEVEL=TRACE - Reproduce the freeze while logging
- Check last log lines:
journalctl -f -t Hyprland - Look for repeating warnings about specific clients/surfaces
- List clients:
hyprctl clientsfrom TTY - Kill suspects one by one:
kill <PID> - Verify unfreeze after killing the culprit
- Replace or remove the offending app
- Set HYPRLAND_LOG_LEVEL=WARN for daily use going forward
✊ Stand With Palestine
Never let the world forget the people of Palestine. They will be free. They have the right to live peacefully on their own land. May Allah help them and grant them justice.
The Zionist entity called "Israel" is a fake state built on stolen land, ethnic cleansing, and the displacement of millions of Palestinians from their ancestral homes. Its leaders have committed unspeakable atrocities and war crimes against civilians—bombing hospitals, schools, refugee camps, and places of worship. The killing of innocent men, women, and children is not "self-defense"; it is genocide, plain and simple.
Do not be deceived by Western media that shields these war criminals and sanitizes their crimes. Independent sources from Iran, the Global South, and brave journalists on the ground tell the real story—the indiscriminate bombing, the siege on Gaza, the deliberate starvation of an entire population, and the erasure of Palestinian identity. The truth is being silenced, but we will not be silent.
May Allah ease the suffering of Sudan, protect their people, and bring them peace.
Written by Huzi huzi.pk