Skip to main content

Hyprlock Crash Protection: Three Layers of Lock Screen Safety on Hyprland

Hyprlock can crash during suspend/resume cycles, leaving your Hyprland session unlocked. Here's how to build a three-layer defense with a watchdog script, systemd-managed hypridle, and a resume guard — so your lock screen always comes back.

· By Ulrich Bojko · 5 min read

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:

  1. You lock your screen (Super+Ctrl+L or a dedicated lock key)
  2. After a few minutes of inactivity, monitors turn off (DPMS)
  3. After 30 minutes, the system suspends
  4. Hours later, something wakes the system (Bluetooth event, USB device, scheduled wake)
  5. 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 with journalctl -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_cmd now uses the watchdog wrapper instead of plain hyprlock
  • after_sleep_cmd now does two things: turns on the display AND checks if hyprlock is still alive. If hyprlock crashed during resume, it triggers loginctl lock-session, which fires the lock_cmd again (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:

  1. You press Super+Ctrl+Lloginctl lock-session fires
  2. Hypridle catches it → runs lock_cmd → starts watchdog → starts hyprlock
  3. 8 minutes idle → brightness dims to 10%
  4. 10 minutes idle → (already locked, no-op)
  5. 11 minutes idle → monitors turn off (DPMS)
  6. 30 minutes idle → system suspends (before_sleep_cmd locks session again for safety)
  7. Morning: something wakes the PCafter_sleep_cmd runs:
  8. Turns on DPMS
  9. Checks if hyprlock is alive
  10. If not → loginctl lock-session → watchdog → fresh hyprlock
  11. If hyprlock crashes during resume → watchdog catches it, restarts immediately
  12. 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.

Updated on Feb 12, 2026