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
- Enable the tauri 'image-png' feature in Cargo.toml: tauri = { version = "2", features = ["image-png", "tray-icon"] }.
- Verify ../icons/32x32.png is a valid PNG (file icons/32x32.png; ensure it is not a Git LFS pointer or truncated file).
- Alternatively use Image::from_path at build/first-run, or decode with the image crate and pass raw RGBA to Image::new_owned.
- 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
- Enable the tauri 'image-png' feature when embedding PNGs for tray/window icons.
- Add a unit test that decodes include_bytes!("../icons/32x32.png") in CI to catch corrupt/renamed assets.
- Verify icons after git LFS checkouts and merges (LFS pointer files look like text, not PNGs).
- Provide a hard-coded fallback icon so a bad asset degrades instead of aborting startup.
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
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Invalid server URL
- Failed to build Tauri application
- Failed to create tokio runtime for embedded server
- Failed to start OpenFang server
- Failed to set listener to non-blocking
AI-assisted analysis of RightNow-AI/openfang@acf2587e46 (2026-09-02).
Data as JSON: /api/errors/f501d6d315226fd0.
Report an issue: GitHub.