RightNow-AI/openfang · error

Failed to decode tray icon PNG

Error message

Failed to decode tray icon PNG

What it means

This panic comes from `tauri::image::Image::from_bytes(include_bytes!("../icons/32x32.png")).expect(...)` in setup_tray (crates/openfang-desktop/src/tray.rs:109). The app embeds its tray icon PNG at compile time and decodes it at runtime; Tauri's Image::from_bytes expects raw decoded RGBA data or a recognized format and returns an Err when the byte content cannot be decoded into an Image (it does not auto-decode PNG unless the 'image-png' feature is enabled).

Source

Thrown at crates/openfang-desktop/src/tray.rs:109

        app,
        &[
            &show,
            &browser,
            &sep1,
            &agents_info,
            &status_info,
            &sep2,
            &launch_at_login,
            &check_updates,
            &open_config,
            &sep3,
            &quit,
        ],
    )?;

    // Load the tray icon from embedded PNG bytes
    let tray_icon = tauri::image::Image::from_bytes(include_bytes!("../icons/32x32.png"))
        .expect("Failed to decode tray icon PNG");

    let _tray = TrayIconBuilder::new()
        .icon(tray_icon)
        .menu(&menu)
        .tooltip("OpenFang Agent OS")
        .on_menu_event(move |app, event| match event.id().as_ref() {
            "show" => {
                if let Some(w) = app.get_webview_window("main") {
                    let _ = w.show();
                    let _ = w.unminimize();
                    let _ = w.set_focus();
                }
            }
            "browser" => {
                if let Some(port) = app.try_state::<crate::PortState>() {
                    let url = format!("http://127.0.0.1:{}", port.0);
                    let _ = open::that(&url);
                }

View on GitHub (pinned to acf2587e46)

Solutions

  1. Enable the tauri 'image-png' feature in Cargo.toml: tauri = { version = "2", features = ["image-png", "tray-icon"] }.
  2. Verify ../icons/32x32.png is a valid PNG (file icons/32x32.png; ensure it is not a Git LFS pointer or truncated file).
  3. Alternatively use Image::from_path at build/first-run, or decode with the image crate and pass raw RGBA to Image::new_owned.
  4. Replace expect with graceful error handling so a bad asset logs an error instead of aborting tray setup.

Example fix

// before
let tray_icon = tauri::image::Image::from_bytes(include_bytes!("../icons/32x32.png"))
    .expect("Failed to decode tray icon PNG");
// after (Cargo.toml: tauri features += ["image-png"])
let tray_icon = tauri::image::Image::from_bytes(include_bytes!("../icons/32x32.png"))
    .unwrap_or_else(|e| {
        log::error!("tray icon decode failed: {e}");
        tauri::image::Image::new_rgba(Vec::new(), 32, 32).expect("fallback icon")
    });
Defensive patterns

Strategy: fallback

Validate before calling

// Compile-time sanity: ensure the embedded asset exists and is a PNG
const _: () = assert!(include_bytes!("../icons/32x32.png")[..8] == [0x89, b'P', b'N', b'G', 0x0D, 0x0A, 0x1A, 0x0A]);

Type guard

fn is_png(bytes: &[u8]) -> bool {
    bytes.len() >= 8 && bytes[..8] == [0x89, b'P', b'N', b'G', 0x0D, 0x0A, 0x1A, 0x0A]
}

Try / catch

let tray_icon = tauri::image::Image::from_bytes(include_bytes!("../icons/32x32.png"));
let tray_icon = match tray_icon {
    Ok(img) => img,
    Err(e) => {
        log::error!("tray icon decode failed: {e}");
        return Ok(()); // skip tray setup instead of crashing app startup
    }
};

Prevention

When it happens

Trigger: (1) The tauri 'image-png' (or image-ico) cargo feature is missing, so from_bytes receives compressed PNG bytes it cannot interpret; (2) the embedded ../icons/32x32.png file is corrupt, empty, truncated, or not actually a PNG; (3) the file path in include_bytes! points to a wrong/renamed asset so unrelated bytes are embedded.

Common situations: Upgrading Tauri v1 to v2 and forgetting the image-png feature; replacing icons/icon.png with a mislabeled file (e.g. an SVG or ICO renamed .png); a bad git merge or LFS checkout leaving a pointer file instead of real PNG bytes.

Understand the failure class

Related errors


AI-assisted analysis of RightNow-AI/openfang@acf2587e46 (2026-09-02). Data as JSON: /api/errors/f501d6d315226fd0. Report an issue: GitHub.