# How to Troubleshoot Hyprland Startup Issues: A Complete Technical Guide

> Directly troubleshoot Hyprland startup failures. Learn to check XDG_RUNTIME_DIR permissions, verify configs, use safe mode, and analyze debug logs for a smooth desktop experience.

- Repository: [Hypr Development/Hyprland](https://github.com/hyprwm/Hyprland)
- Tags: how-to-guide
- Published: 2026-07-29

---

**Troubleshoot Hyprland startup failures by checking `XDG_RUNTIME_DIR` permissions, validating configs with `--verify-config`, running in safe mode to isolate plugins, and examining debug logs from [`src/main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/main.cpp) initialization and `CCompositor` construction.**

Hyprland startup issues typically stem from environment misconfigurations, invalid config syntax, or DRM initialization failures. This guide examines the exact launch sequence implemented in the hyprwm/Hyprland source code, tracing how [`src/main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/main.cpp), `ConfigManager`, and `CCompositor` handle initialization to help you diagnose why the compositor exits before displaying windows.

## Understanding the Hyprland Launch Sequence

Hyprland follows a strict nine-phase initialization process defined in [`src/main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/main.cpp) and the core compositor classes. Knowing which phase fails allows you to target fixes efficiently.

1. **Argument Parsing** – [`main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/main.cpp) processes CLI flags, sets environment variables, and validates the supplied config file path (lines 31-40).
2. **Environment Checks** – The compositor verifies `XDG_RUNTIME_DIR` exists and prevents accidental root execution unless `--i-am-really-stupid` is provided (lines 104-108).
3. **Configuration Loading** – `ConfigManager` from [`src/config/ConfigManager.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/config/ConfigManager.cpp) resolves the user config path, generates defaults if missing, and instantiates the Lua-based manager.
4. **Compositor Construction** – `new CCompositor(verifyConfig)` prepares Wayland resources, DRM sync-obj support, and internal managers ([`src/Compositor.hpp`](https://github.com/hyprwm/Hyprland/blob/main/src/Compositor.hpp)).
5. **Watchdog and Socket Handover** – If starting via `start-hyprland`, the compositor binds to the provided socket and connects the watchdog pipe when `--watchdog-fd` or `--socket/--wayland-fd` arguments are present (lines 71-78).
6. **Safe Mode and Lock Handling** – Flags like `--safe-mode` suppress user plugins, while `--locked` initiates the screen locker before the main loop (lines 64-66, 78-82).
7. **Server Initialization** – `g_pCompositor->initServer()` creates the Wayland display, registers global objects, and starts the event loop (implemented in [`src/Compositor.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/Compositor.cpp)).
8. **Runtime Execution** – `startCompositor()` enters the main loop; any exception thrown during construction triggers immediate termination with error output.
9. **Cleanup** – On exit or fatal error, `cleanup()` removes lock files and restores file-descriptor limits.

## Common Startup Failure Points and Diagnostics

### "XDG_RUNTIME_DIR is not set!" Error

This exception originates at line 57 of [`src/main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/main.cpp) when the environment variable is missing or invalid. This commonly occurs on non-systemd init systems.

**Verification:**

```bash
echo $XDG_RUNTIME_DIR

```

If empty, export a valid path owned by your user:

```bash
export XDG_RUNTIME_DIR=/run/user/$(id - u)

```

### Config File Validation Failures

When Hyprland reports "Config file … is invalid", [`main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/main.cpp) (lines 31-40) has failed `std::filesystem::canonical` or `is_regular_file` checks. The path may not exist, may be a directory, or lack read permissions.

**Diagnostic command:**

```bash
Hyprland --verify-config && echo "Config OK" || echo "Config errors!"

```

A non-zero exit indicates syntax errors in `~/.config/hypr/hyprland.conf`.

### Superuser Restrictions

The compositor refuses to start as root without explicit override. At lines 104-108, [`main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/main.cpp) calls `NInit::isSudo()` and aborts unless you provide `--i-am-really-stupid`.

**Check your UID:**

```bash
id -u

```

If the result is `0`, either switch to a regular user or invoke with the override flag (not recommended for daily use).

### Socket Handover Incompleteness

When using `start-hyprland`, the compositor requires both `--socket` and `--wayland-fd` simultaneously. The XOR test at lines 131-136 of [`src/main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/main.cpp) emits an error if only one is supplied.

**Verify the launch script** passes both file descriptors:

```bash
Hyprland --socket hyprland --wayland-fd "$FD"

```

### Watchdog Timeouts

The `--watchdog-fd` parameter (line 71) must indicate a valid file descriptor. If the pipe closes prematurely, the compositor assumes the parent process died.

**Inspect watchdog status** by running with debug output:

```bash
HYPRLAND_DEBUG=1 Hyprland 2>&1 | grep -i watchdog

```

### Compositor Construction Crashes

Exceptions thrown from `CCompositor` during instantiation (e.g., DRM device initialization failures, missing Wayland backends) are caught at lines 62-67 of [`src/main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/main.cpp), printing the exception text before abort.

**Capture the full stack trace:**

```bash
HYPRLAND_DEBUG=1 Hyprland

```

Look for errors originating from `CCompositor` constructor or `initServer()`.

### Plugin Loading Failures

Corrupt or incompatible `.so` files in your plugin directory cause aborts during `PluginManager` initialization in [`src/hyprpm/src/core/PluginManager.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/hyprpm/src/core/PluginManager.cpp).

**Check plugin logs:**

```bash
journalctl -xe | grep -i hyprland

# Or inspect:

cat ~/.local/share/hyprland/log

```

## Diagnostic Commands and Solutions

When Hyprland fails to start, use this systematic approach to isolate the component responsible.

### Run in Safe Mode

**Safe mode** (`--safe-mode`) disables user-defined plugins and skips risky config sections. If Hyprland starts in this mode, the issue lies in your configuration or a specific plugin.

```bash
Hyprland --safe-mode

```

### Validate Configuration Only

Validate syntax without launching the compositor:

```bash
Hyprland --verify-config

```

Exit code `0` confirms valid syntax; any other value indicates `ConfigManager` detected errors.

### Enable Full Debug Logging

Set the `HYPRLAND_DEBUG` environment variable to capture verbose output from [`main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/main.cpp) initialization and `CCompositor` setup:

```bash
HYPRLAND_DEBUG=1 Hyprland --safe-mode 2>&1 | tee hyprland-debug.log

```

### Check XWayland Initialization

Black screens or missing X11 application support often trace to `XWaylandManager` failures in [`src/xwayland/Server.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/xwayland/Server.cpp). Enable rendering debug in your config:

```conf
debug:disable_logs = false
debug:enable_stdout_logs = true

```

Then review logs for XWayland server startup messages.

### Examine File Descriptor Limits

Low file-descriptor limits cause silent failures during `initServer()`. The [`initHelpers.hpp`](https://github.com/hyprwm/Hyprland/blob/main/initHelpers.hpp) utilities attempt to raise limits, but manual verification helps:

```bash
ulimit -n

```

Values below `1024` may cause resource exhaustion during startup.

## Summary

- **Environment first**: Verify `XDG_RUNTIME_DIR` is set and writable before launching Hyprland.
- **Check permissions**: Never run as root without `--i-am-really-stupid`; confirm your user owns the runtime directory.
- **Validate configs**: Use `Hyprland --verify-config` to catch syntax errors before they crash the compositor.
- **Isolate problems**: Start with `--safe-mode` to determine if plugins or config sections cause the failure.
- **Review logs**: Enable `HYPRLAND_DEBUG=1` to capture exact failure points in [`src/main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/main.cpp) and `CCompositor` construction.
- **Socket handover**: When using `start-hyprland`, ensure both `--socket` and `--wayland-fd` arguments are present to avoid initialization aborts.

## Frequently Asked Questions

### Why does Hyprland say "XDG_RUNTIME_DIR is not set!" on startup?

Hyprland requires the `XDG_RUNTIME_DIR` environment variable to create Wayland sockets and state files. At line 57 of [`src/main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/main.cpp), the compositor checks this variable and aborts if missing. Set it to a user-owned directory like `/run/user/$(id - u)` before launching, typically handled by your login manager or systemd.

### What is the difference between `--safe-mode` and `--verify-config`?

`--safe-mode` launches the compositor but disables all user plugins and suppresses certain config-driven features, helping you identify if third-party code causes the crash. `--verify-config` performs a dry-run validation in `ConfigManager` and exits immediately with status `0` for valid configs or non-zero for syntax errors, without starting the graphics stack.

### How do I fix "Only one of --socket and --wayland-fd supplied" errors?

This error at lines 131-136 of [`src/main.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/main.cpp) indicates incomplete socket handover, usually when the `start-hyprland` wrapper malfunctions. Ensure the script passes both descriptors simultaneously: `--socket NAME --wayland-fd NUMBER`. Both arguments are required for the compositor to adopt an existing socket.

### Why does Hyprland crash immediately without showing the splash screen?

Immediate crashes during `CCompositor` construction (before `setRandomSplash` executes) typically indicate DRM initialization failures, missing `/dev/dri` permissions, or incompatible Mesa/drivers. Run with `HYPRLAND_DEBUG=1` to expose the exception thrown during `initServer()` in [`src/Compositor.cpp`](https://github.com/hyprwm/Hyprland/blob/main/src/Compositor.cpp), which normally outputs the specific backend failure to stderr.