elkowar/eww · error

no pixbuf from theme.load_icon despite no error

Error message

no pixbuf from theme.load_icon despite no error

What it means

This is an .expect() on the Option inside Ok(pb) from theme.load_icon_for_scale: the GTK docs say that when load_icon_for_scale returns Ok the pixbuf may still be None. GTK yields Ok(None) in edge cases (e.g. the icon resolved to nothing usable for the requested size/scale, such as an empty or malformed icon theme entry), so the crate treats it as an internal invariant violation and panics.

Solutions

  1. Treat Ok(None) as a lookup failure: fall back to the fallback_icon('image-missing') path instead of panicking
  2. Validate the icon name / theme_path from the SNI item and log it when the lookup yields None
  3. Update GTK (gtk3/glib) packages — some versions had Ok(None) quirks with FORCE_SIZE at unusual scale factors
  4. Map None to an IconError (e.g. IconError::NotAvailable) so callers can degrade gracefully
  5. Ensure a complete icon theme is installed so lookups resolve for all sizes/scales

Example fix

// before
Ok(pb) => Ok(pb.expect("no pixbuf from theme.load_icon despite no error")),
// after
Ok(Some(pb)) => Ok(pb),
Ok(None) => {
    log::warn!("theme returned no pixbuf for \"{}\" at {}px", icon_name, size);
    Err(IconError::NotAvailable)
}
Defensive patterns

Strategy: fallback

Validate before calling

// Validate inputs before the lookup
if icon_name.trim().is_empty() { return Err(IconError::NotAvailable); }
if let Some(p) = theme_path {
    if !std::path::Path::new(p).exists() { log::warn!("theme path missing: {}", p); }
}

Type guard

fn pixbuf_from_ok(pb: Option<gtk::gdk_pixbuf::Pixbuf>) -> Option<gtk::gdk_pixbuf::Pixbuf> {
    pb.filter(|p| p.width() > 0 && p.height() > 0)
}

Try / catch

match theme.load_icon_for_scale(icon_name, size, scale, gtk::IconLookupFlags::FORCE_SIZE) {
    Ok(Some(pb)) => Ok(pb),
    Ok(None) | Err(_) => fallback_icon(size, scale)
        .map(Ok)
        .unwrap_or(Err(IconError::NotAvailable)),
}

Prevention

When it happens

Trigger: load_icon_from_sni -> icon_from_name calls theme.load_icon_for_scale(icon_name, size, scale, FORCE_SIZE) and GTK returns Ok(None) — observed with icon names that do not resolve cleanly in the (possibly custom, theme_path-prepended) theme at the requested size/scale.

Common situations: Tray items advertising icon names absent from the theme while the theme lookup still 'succeeds'; HiDPI scale factors where no scaled variant exists; custom theme paths (prepend_search_path) pointing at incomplete icon theme directories; broken cached pixbufs in some GTK versions.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of elkowar/eww@48f5aa8b37 (2026-09-08). Data as JSON: /api/errors/73da75ff2eed1167. Report an issue: GitHub.

Appendix: source

Thrown at crates/notifier_host/src/icon.rs:115

/// Load an icon with a given name from either the default (if `theme_path` is `None`), or from the
/// theme at a path.
fn icon_from_name(
    icon_name: &str,
    theme_path: Option<&str>,
    size: i32,
    scale: i32,
) -> std::result::Result<gtk::gdk_pixbuf::Pixbuf, IconError> {
    let theme = if let Some(path) = theme_path {
        let theme = gtk::IconTheme::new();
        theme.prepend_search_path(path);
        theme
    } else {
        gtk::IconTheme::default().expect("Could not get default gtk theme")
    };

    match theme.load_icon_for_scale(icon_name, size, scale, gtk::IconLookupFlags::FORCE_SIZE) {
        Ok(pb) => Ok(pb.expect("no pixbuf from theme.load_icon despite no error")),
        Err(e) => Err(IconError::LoadIconFromTheme {
            icon_name: icon_name.to_owned(),
            theme_path: theme_path.map(str::to_owned),
            source: e,
        }),
    }
}

pub async fn load_icon_from_sni(
    sni: &proxy::StatusNotifierItemProxy<'_>,
    size: i32,
    scale: i32,
) -> Option<gtk::gdk_pixbuf::Pixbuf> {
    // "Visualizations are encouraged to prefer icon names over icon pixmaps if both are
    // available."

    let scaled_size = size * scale;

View on GitHub (pinned to 48f5aa8b37)