tauri-apps/tauri · error

failed to open icon

Error message

failed to open icon {}: {}

What it means

CachedIcon::open reads the icon file from disk with std::fs::read during macro expansion. Any IO failure (missing file, permission denied, path is a directory) panics with `failed to open icon {path}: {io error}`, aborting the build before any decoding happens.

Solutions

  1. Fix the icon path so it resolves relative to the invoking crate (use CARGO_MANIFEST_DIR-based paths if needed)
  2. Confirm the file exists with correct casing (`ls src/icons/`)
  3. Commit the icon to the repo and un-ignore it
  4. Replace the directory path with the path to the actual file

Example fix

// before
let icon = tauri::icon!("../branding/logo.ico");
// after
let icon = tauri::icon!(concat!(env!("CARGO_MANIFEST_DIR"), "/icons/logo.ico"));
Defensive patterns

Strategy: validation

Validate before calling

import os, sys
p = os.path.join(os.environ.get('CARGO_MANIFEST_DIR',''), 'icons/logo.ico')
if not os.path.isfile(p):
    sys.exit(f'icon missing: {p}')

Prevention

When it happens

Trigger: The icon path passed to icon!/embedded assets does not exist or is unreadable: typo in path, path relative to the wrong crate root, file deleted, or a directory passed instead of a file.

Common situations: Referencing icons/32x32.png that only exists in another crate; case mismatch on Linux/CI; icons excluded by .gitignore so CI checkouts lack them; running the build from a workspace where the relative path differs.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of tauri-apps/tauri@460ec35447 (2026-09-18). Data as JSON: /api/errors/dfbea57a321cc247. Report an issue: GitHub.

Appendix: source

Thrown at crates/tauri-codegen/src/image.rs:102

    }

    let mut rgba = Vec::with_capacity(reader.output_buffer_size().unwrap());
    while let Ok(Some(row)) = reader.next_row() {
      rgba.extend(row.data());
    }

    Cached::try_from(rgba).map(|cache| Self {
      cache,
      root: root.clone(),
      format: IconFormat::Image {
        width: reader.info().width,
        height: reader.info().height,
      },
    })
  }

  fn open(path: &Path) -> Vec<u8> {
    std::fs::read(path).unwrap_or_else(|e| panic!("failed to open icon {}: {}", path.display(), e))
  }
}

impl ToTokens for CachedIcon {
  fn to_tokens(&self, tokens: &mut TokenStream) {
    let root = &self.root;
    let cache = &self.cache;
    let raw = quote!(::std::include_bytes!(#cache));
    tokens.append_all(match self.format {
      IconFormat::Raw => raw,
      IconFormat::Image { width, height } => {
        quote!(#root::image::Image::new(#raw, #width, #height))
      }
    })
  }
}

View on GitHub (pinned to 460ec35447)