tauri-apps/tauri · error

failed to read resource file name

Error message

failed to read resource file name

What it means

generate_resource_data builds a ResourceFile for each bundled resource and takes the leaf name of the resource's target path via file_name().expect("failed to read resource file name"). When the configured target path has no final component (ends in a separator, is empty, or is '..'/root), the panic fires.

Solutions

  1. Fix the resources entry so each target path names a file or ends in a concrete directory name (no trailing slash / '..').
  2. Verify with the resolved target path printed in build logs which entry is malformed.
  3. Guard the code by falling back to the source file name when the target has none.

Example fix

// before (tauri.conf.json)
"resources": ["assets/*->/"]

// after
"resources": ["assets/*->assets/"]
Defensive patterns

Strategy: validation

Validate before calling

// validate resources targets in tauri.conf.json before bundling
for r in resources {
  let t = r.target();
  if t.file_name().is_none() {
    return Err(anyhow!("resource target has no filename: {}", t.display()));
  }
}

Type guard

fn has_filename(p: &std::path::Path) -> bool { p.file_name().is_some() }

Try / catch

// isolate the bundler in a subprocess; on this panic, point at the resources
// entry whose target ends with a separator, is empty, or is '..'/root.

Prevention

When it happens

Trigger: Calling bundle_project with a bundle.resources entry whose target (path after '->' or the mapped destination) is a directory root or ends with '/'/'..', so resource.target().file_name() is None.

Common situations: Resources mapped like "assets/->/" or a target written with a trailing slash in tauri.conf.json, or resources entries that resolve to the drive root on Windows.

Related errors


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

Appendix: source

Thrown at crates/tauri-bundler/src/bundle/windows/msi/mod.rs:1027

    // In some glob resource paths like `assets/**/*` a file might appear twice
    // because the `tauri_utils::resources::ResourcePaths` iterator also reads a directory
    // when it finds one. So we must check it before processing the file.
    if added_resources.contains(&resource_path) {
      continue;
    }
    added_resources.insert(resource_path.clone());

    if settings.windows().can_sign() && should_sign(&resource_path)? {
      try_sign(&resource_path, settings)?;
    }

    let resource_entry = ResourceFile::new(
      resource_path,
      Some(
        resource
          .target()
          .file_name()
          .expect("failed to read resource file name")
          .to_string_lossy()
          .into_owned(),
      ),
    );

    let target_path = resource.target();
    let components_count = target_path.components().count();
    let directories = target_path
      .components()
      .take(components_count - 1) // the last component is the file
      .collect::<Vec<_>>();

    let mut directory_entry = &mut root_resource_directory;

    for directory in directories {
      let directory_name = directory
        .as_os_str()
        .to_os_string()

View on GitHub (pinned to 460ec35447)