niri-wm/niri · warning · anyhow::Error

no default icon

Error message

no default icon

What it means

load_xcursor resolves a cursor name through the xcursor theme lookup (theme.load_icon(name)), which searches the configured theme and its inherited chain in ~/.icons, ~/.local/share/icons and /usr/share/icons. 'no default icon' means the lookup returned None: no cursor theme on disk provides an icon for that name. niri treats this softly: for most icons it logs 'error loading xcursor ...' and falls back to the default, and for CursorIcon::Default it falls back to a built-in cursor, so the visible symptom is a wrong/legacy pointer rather than a crash.

Source

Thrown at src/cursor.rs:164

    /// Currently used cursor_image as a cursor provider.
    pub fn cursor_image(&self) -> &CursorImageStatus {
        &self.current_cursor
    }

    /// Set new cursor image provider.
    pub fn set_cursor_image(&mut self, cursor: CursorImageStatus) {
        self.current_cursor = cursor;
    }

    /// Load the cursor with the given `name` from the file system picking the closest
    /// one to the given `size`.
    fn load_xcursor(theme: &CursorTheme, name: &str, size: i32) -> anyhow::Result<XCursor> {
        let _span = tracy_client::span!("load_xcursor");

        let path = theme
            .load_icon(name)
            .ok_or_else(|| anyhow!("no default icon"))?;

        let mut file = File::open(path).context("error opening cursor icon file")?;
        let mut buf = vec![];
        file.read_to_end(&mut buf)
            .context("error reading cursor icon file")?;

        let mut images = parse_xcursor(&buf).context("error parsing cursor icon file")?;

        let (width, height) = images
            .iter()
            .min_by_key(|image| (size - image.size as i32).abs())
            .map(|image| (image.width, image.height))
            .unwrap();

        images.retain(move |image| image.width == width && image.height == height);

        let animation_duration = images.iter().fold(0, |acc, image| acc + image.delay);

View on GitHub (pinned to 606284464d)

Solutions

  1. Install a complete cursor theme: e.g. 'pacman -S bibata-cursor-theme' / 'apt install breeze-cursor-theme' / 'dnf install google-crosextra-carlito...' style package for your distro, plus adwaita-icon-theme as a fallback.
  2. Point niri at a theme that actually exists: check 'ls ~/.icons ~/.local/share/icons /usr/share/icons' and set the config to the exact directory name: cursor { xcursor-theme "Bibata-Modern-Classic"; xcursor-size 24 }.
  3. Verify the theme provides the default cursor: 'find /usr/share/icons/<theme> -name "left_ptr*" -o -name "default*"' should return files.
  4. Clear stale caches/paths: unset weird XCURSOR_PATH and confirm XCURSOR_THEME matches the installed theme name.

Example fix

// before: theme not installed, every lookup logs "no default icon"
cursor {
    xcursor-theme "MyMissingTheme"
    xcursor-size 24
}

// after: theme that exists in /usr/share/icons
cursor {
    xcursor-theme "Adwaita"
    xcursor-size 24
}
Defensive patterns

Strategy: fallback

Validate before calling

// Rust: confirm the theme exists and exposes a default cursor before using it
let theme = CursorTheme::new(&name, &search_paths);
let ok = theme
    .load_icon("left_ptr")
    .or_else(|| theme.load_icon("default"))
    .is_some();
anyhow::ensure!(ok, "cursor theme '{name}' provides no default cursor; is it installed?");

Try / catch

match Self::load_xcursor(&theme, icon.name(), size) {
    Ok(x) => Some(Rc::new(x)),
    Err(_) => {
        // niri's own pattern: unknown icons degrade to the default, default falls back to built-in
        warn!("error loading xcursor {}, using fallback", icon.name());
        None // caller substitutes the default/built-in cursor
    }
}

Prevention

When it happens

Trigger: Calling Manager::load_xcursor with a theme whose directory exists but lacks the requested icon file (e.g. a theme with only a few cursors installed), or when the configured cursor theme is not installed at all and no default theme (Adwaita/default) exists on a minimal system; also when XCURSOR_PATH/XCURSOR_THEME point somewhere unusual.

Common situations: Setting cursor-theme in niri config (or XCURSOR_THEME) to a theme that is not installed or has a different name than its directory; minimal distros/containers with no cursor theme package; partial theme installs where 'default'/'left_ptr' aliases are missing; typos in the theme name.

Related errors


AI-assisted analysis of niri-wm/niri@606284464d (2026-08-16). Data as JSON: /api/errors/28384e887de0cf32. Report an issue: GitHub.