If you use Hyprland as your Wayland compositor, you’ve probably adopted hyprlock as your lock screen and hypridle as your idle daemon. It’s a clean, well-integrated setup — until one morning you wake up to find hyprlock has crashed overnight and your session is wide open.
This guide walks through why hyprlock crashes happen and how to build a three-layer defense that keeps your session protected no matter what.
The Problem
Here’s a typical lock-and-sleep workflow on Hyprland:
- You lock your screen (
Super+Ctrl+Lor a dedicated lock key) - After a few minutes of inactivity, monitors turn off (DPMS)
- After 30 minutes, the system suspends
- Hours later, something wakes the system (Bluetooth event, USB device, scheduled wake)
- hyprlock should show the lock screen — but it has crashed
The crash typically happens during the suspend/resume cycle. AMD GPUs (especially integrated Radeon graphics) are particularly prone to this: the GPU resources hyprlock holds become invalid when the display hardware powers down and back up.
When hyprlock crashes, you’re left with an unlocked desktop. If you’re away from your machine, that’s a security problem.
The Solution: Three Layers of Protection
Rather than hoping for a bug fix, we can build resilience into the system. Each layer catches failures the previous one might miss.
Layer 1: Hyprlock Watchdog Script
The most important piece. Instead of running hyprlock directly, we wrap it in a script that monitors its exit code and restarts it on crash.
Create ~/.config/hypr/scripts/hyprlock-watchdog.sh:
#!/usr/bin/env bash
# -----------------------------------------------
# Hyprlock Watchdog
# Wraps hyprlock and restarts it if it crashes.
# If it keeps crashing, suspends the system as a
# safety measure to protect the unlocked session.
# -----------------------------------------------
MAX_RESTARTS=5
RESTART_DELAY=1
CRASH_WINDOW=60 # Reset crash counter if stable for this many seconds
# Don't start if hyprlock is already running
if pidof hyprlock > /dev/null 2>&1; then
exit 0
fi
crash_count=0
while [ $crash_count -lt $MAX_RESTARTS ]; do
start_time=$(date +%s)
hyprlock
exit_code=$?
# Exit code 0 = normal unlock by user
if [ $exit_code -eq 0 ]; then
exit 0
fi
end_time=$(date +%s)
runtime=$((end_time - start_time))
# If hyprlock ran for a while before crashing, reset the counter
# (it was stable, this is likely a new/different issue)
if [ $runtime -ge $CRASH_WINDOW ]; then
crash_count=1
else
crash_count=$((crash_count + 1))
fi
logger -t hyprlock-watchdog "hyprlock crashed with exit code $exit_code after ${runtime}s (crash $crash_count/$MAX_RESTARTS)"
notify-send -u critical "Lock Screen" "hyprlock crashed (exit $exit_code). Restarting... ($crash_count/$MAX_RESTARTS)"
sleep $RESTART_DELAY
done
# Exhausted restart attempts — suspend to protect the session
logger -t hyprlock-watchdog "hyprlock crashed $MAX_RESTARTS times in rapid succession. Suspending system."
notify-send -u critical "Lock Screen" "hyprlock keeps crashing. Suspending system for safety."
sleep 2
systemctl suspend
Make it executable:
chmod +x ~/.config/hypr/scripts/hyprlock-watchdog.sh
How it works:
- When hyprlock exits with code 0 (user unlocked successfully), the watchdog exits too
- When hyprlock crashes (non-zero exit), the watchdog restarts it immediately
- If hyprlock ran for over 60 seconds before crashing, the crash counter resets (it was a one-off, not a crash loop)
- If hyprlock crashes 5 times in rapid succession, the watchdog gives up and suspends the system — better to suspend than leave the session exposed
- Every crash is logged via
logger(check withjournalctl -t hyprlock-watchdog) and shown as a notification
Layer 2: Systemd-Managed Hypridle
By default, most Hyprland setups start hypridle via exec-once in the Hyprland config. This is fire-and-forget: if hypridle crashes, it’s gone and your idle/lock/suspend chain is broken.
Hyprland ships a systemd user service at /usr/lib/systemd/user/hypridle.service with Restart=on-failure. If we use this instead, systemd will automatically restart hypridle when it crashes.
Step 1: Comment out the exec-once line in your autostart config (~/.config/hypr/conf/autostart.conf):
# hypridle is now managed by systemd (systemctl --user enable --now hypridle.service)
# exec-once = hypridle
Step 2: Enable and start the systemd service:
# Enable it (starts automatically on future logins)
systemctl --user enable hypridle.service
# Start it now (for the current session)
systemctl --user start hypridle.service
# Kill the old exec-once instance if it's still running
# Check PIDs first:
pgrep -a hypridle
# Kill the one that ISN'T the systemd-managed one (lower PID, usually)
kill <old-pid>
Step 3: Verify:
systemctl --user status hypridle.service
You should see Active: active (running) and Restart: on-failure.
Layer 3: Resume Guard in Hypridle
The final layer addresses the most dangerous moment: waking up from suspend. This is when hyprlock is most likely to crash (GPU resources are reinitialized, display state changes).
Update your ~/.config/hypr/hypridle.conf general section:
general {
lock_cmd = pidof hyprlock || ~/.config/hypr/scripts/hyprlock-watchdog.sh
before_sleep_cmd = loginctl lock-session
after_sleep_cmd = hyprctl dispatch dpms on && (pidof hyprlock > /dev/null || loginctl lock-session)
}
The key changes:
lock_cmdnow uses the watchdog wrapper instead of plain hyprlockafter_sleep_cmdnow does two things: turns on the display AND checks if hyprlock is still alive. If hyprlock crashed during resume, it triggersloginctl lock-session, which fires thelock_cmdagain (launching the watchdog with a fresh hyprlock)
Bonus: Consistent Keybindings
If your keybindings call hyprlock directly, they bypass the watchdog. Update them to use loginctl lock-session instead, which goes through hypridle’s lock_cmd:
In ~/.config/hypr/conf/keybindings/default.conf:
# Before (bypasses watchdog):
# bind = $mainMod CTRL, L, exec, hyprlock
# bind = , XF86Lock, exec, hyprlock
# After (goes through hypridle's lock_cmd → watchdog):
bind = $mainMod CTRL, L, exec, loginctl lock-session
bind = , XF86Lock, exec, loginctl lock-session
If you have a power.sh script that calls hyprlock directly for its lock action, you can update that too — or just rebind the key to skip the script entirely.
The Complete Flow
Here’s what happens now when you lock your PC and go to bed:
- You press Super+Ctrl+L →
loginctl lock-sessionfires - Hypridle catches it → runs
lock_cmd→ starts watchdog → starts hyprlock - 8 minutes idle → brightness dims to 10%
- 10 minutes idle → (already locked, no-op)
- 11 minutes idle → monitors turn off (DPMS)
- 30 minutes idle → system suspends (
before_sleep_cmdlocks session again for safety) - Morning: something wakes the PC →
after_sleep_cmdruns: - Turns on DPMS
- Checks if hyprlock is alive
- If not →
loginctl lock-session→ watchdog → fresh hyprlock - If hyprlock crashes during resume → watchdog catches it, restarts immediately
- If hyprlock keeps crashing → system suspends as a safety net
At every point, something is watching something else. There’s no single point of failure.
Verifying Your Setup
After making all the changes:
# Reload Hyprland config
hyprctl reload
# Verify hypridle is running via systemd
systemctl --user status hypridle.service
# Test locking
loginctl lock-session
# Check watchdog logs after a lock/unlock cycle
journalctl -t hyprlock-watchdog --no-pager
# Monitor in real-time (in a separate terminal before locking)
journalctl -t hyprlock-watchdog -f
Troubleshooting
Hypridle won’t start via systemd: Check that WAYLAND_DISPLAY is set in your environment. The service requires it (ConditionEnvironment=WAYLAND_DISPLAY). If you’re having issues, run systemctl --user show-environment | grep WAYLAND.
Two hypridle processes running: You probably forgot to kill the old exec-once instance or forgot to comment it out. Run pgrep -a hypridle and kill the one not managed by systemd.
Lock screen never appears after resume: Check journalctl --user -u hypridle.service for errors. Make sure the after_sleep_cmd syntax is correct (the pidof check needs /dev/null redirection).
Watchdog suspends immediately: If hyprlock keeps crashing in a loop (5 times), the watchdog suspends for safety. Check journalctl -t hyprlock-watchdog for the exit codes. Common causes: GPU driver issues (try updating mesa/amdgpu), or Wayland protocol mismatches (update hyprlock).
Summary
| Layer | Protects Against | Mechanism |
|---|---|---|
| Watchdog script | hyprlock crashes | Restarts hyprlock on non-zero exit, suspends after repeated failures |
| Systemd hypridle | hypridle crashes | Restart=on-failure in the systemd service |
| Resume guard | Crash during wake from suspend | after_sleep_cmd checks for hyprlock and re-locks if missing |
| Consistent keybindings | Manual lock bypassing watchdog | All lock paths go through loginctl lock-session → hypridle → watchdog |
The system went from “one crash = exposed session” to “multiple independent safety nets.” Your lock screen might still crash — but now something is always watching, ready to restart it or suspend the machine before your session is left unprotected.