{"record":{"id":"e0feac977d3961a6","repo":"tauri-apps/tauri","slug":"can-t-extract-file-name-from-path","errorCode":null,"errorMessage":"Can't extract file name from path","messagePattern":"Can't extract file name from path","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tauri-bundler/src/bundle/updater_bundle.rs","lineNumber":211,"sourceCode":"    log::info!(action = \"Bundling\"; \"{}\", display_path(&archived_path));\n\n    // Create our gzip file\n    create_zip(&source_path, &archived_path).with_context(|| \"Failed to zip update bundle\")?;\n\n    installers_archived_paths.push(archived_path);\n  }\n\n  Ok(installers_archived_paths)\n}\n\npub fn create_zip(src_file: &Path, dst_file: &Path) -> crate::Result<PathBuf> {\n  let parent_dir = dst_file.parent().expect(\"No data in parent\");\n  fs::create_dir_all(parent_dir)?;\n  let writer = fs_utils::create_file(dst_file)?;\n\n  let file_name = src_file\n    .file_name()\n    .expect(\"Can't extract file name from path\");\n\n  let mut zip = zip::ZipWriter::new(writer);\n  let options = SimpleFileOptions::default()\n    .compression_method(zip::CompressionMethod::Stored)\n    .unix_permissions(0o755);\n\n  zip.start_file(file_name.to_string_lossy(), options)?;\n  let mut f =\n    File::open(src_file).fs_context(\"failed to open updater ZIP file\", src_file.to_path_buf())?;\n\n  let mut buffer = Vec::new();\n  f.read_to_end(&mut buffer)?;\n  zip.write_all(&buffer)?;\n  buffer.clear();\n\n  Ok(dst_file.to_owned())\n}\n","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/tauri-apps/tauri/blob/460ec35447493200d64290dd7f015d5a91d0fd58/crates/tauri-bundler/src/bundle/updater_bundle.rs#L193-L229","documentation":"This panic comes from an `.expect()` on `Path::file_name()` inside `create_zip`, which builds the Windows updater `.zip`. `file_name()` returns `None` when the source path ends in `..`, is a bare root/prefix (e.g. `/`, `C:\\`), or is empty. The bundler treats this as an unrecoverable invariant: it must embed a file name in the zip archive, so it panics instead of returning an error.","triggerScenarios":"Calling `create_zip(src_file, dst_file)` with a `src_file` that has no final component: a path ending in `..` (e.g. `target/release/bundle/..`), a root path (`/` or `C:\\`), or a path normalized to empty. Reached via `bundle_update_windows` during Windows updater bundle generation.","commonSituations":"Build scripts or config passing a directory path with a trailing `..` (often from `PathBuf::push`/`join` with `..` components), paths built from environment variables or CLI args that were never canonicalized, or programmatically constructed paths stripped down to the root.","solutions":["Canonicalize the source path before bundling (`src_file.canonicalize()?` or `std::fs::canonicalize`) so `..` and relative segments are resolved and `file_name()` yields a real component","Ensure the updater bundle path passed to tauri-bundler points to the actual artifact file, not a parent directory or root","If constructing paths programmatically, avoid `join(\"..\")`; use `path.parent()` to move up instead","If you control the caller, validate `src_file.file_name().is_some()` before calling and surface a clear error"],"exampleFix":"// before\nlet src = PathBuf::from(\"/build/app/..\");\ncreate_zip(&src, &dst)?; // panics\n// after\nlet src = PathBuf::from(\"/build/app\").canonicalize()?;\nassert!(src.is_file());\ncreate_zip(&src, &dst)?;","handlingStrategy":"validation","validationCode":"fn ensure_file_name(p: &std::path::Path) -> Result<(), String> {\n    if p.file_name().is_none() {\n        return Err(format!(\"path has no file name component: {}\", p.display()));\n    }\n    Ok(())\n}\n// call ensure_file_name(&src_file)? before create_zip","typeGuard":"fn has_file_name(p: &std::path::Path) -> bool {\n    p.file_name().is_some()\n}","tryCatchPattern":null,"preventionTips":["Canonicalize all artifact paths with std::fs::canonicalize before passing them to the bundler","Never end paths in `..`; use parent() for directory navigation","Assert the updater source is a regular file before bundling","In CI, print resolved absolute paths before invoking the bundler to catch path-assembly bugs early"],"tags":["path","panic","updater","windows"],"backgroundTag":"invalid-argument-value","analyzedSha":"460ec35447493200d64290dd7f015d5a91d0fd58","analyzedAt":"2026-09-18T23:55:51.277Z","contentChangedAt":"2026-09-18T23:55:51.277Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}