{"record":{"id":"fa6d08fa77816d12","repo":"tauri-apps/tauri","slug":"failed-to-extract-merge-module-filename","errorCode":null,"errorMessage":"failed to extract merge module filename","messagePattern":"failed to extract merge module filename","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tauri-bundler/src/bundle/windows/msi/mod.rs","lineNumber":985,"sourceCode":"struct MergeModule {\n  name: String,\n  path: String,\n}\n\nfn get_merge_modules(settings: &Settings) -> crate::Result<Vec<MergeModule>> {\n  let mut merge_modules = Vec::new();\n  let regex = Regex::new(r\"[^\\w\\d\\.]\")?;\n  for msm in glob::glob(\n    &PathBuf::from(glob::Pattern::escape(\n      &settings.project_out_directory().to_string_lossy(),\n    ))\n    .join(\"*.msm\")\n    .to_string_lossy(),\n  )? {\n    let path = msm?;\n    let filename = path\n      .file_name()\n      .expect(\"failed to extract merge module filename\")\n      .to_os_string()\n      .into_string()\n      .expect(\"failed to convert merge module filename to string\");\n    merge_modules.push(MergeModule {\n      name: regex.replace_all(&filename, \"\").to_string(),\n      path: path.to_string_lossy().to_string(),\n    });\n  }\n  Ok(merge_modules)\n}\n\n/// Generates the data required for the resource bundling on wix\nfn generate_resource_data(settings: &Settings) -> crate::Result<ResourceDirectory> {\n  let cwd = std::env::current_dir()?;\n\n  let mut root_resource_directory = ResourceDirectory::default();\n  let mut added_resources = HashSet::new();\n","sourceCodeStart":967,"sourceCodeEnd":1003,"githubUrl":"https://github.com/tauri-apps/tauri/blob/460ec35447493200d64290dd7f015d5a91d0fd58/crates/tauri-bundler/src/bundle/windows/msi/mod.rs#L967-L1003","documentation":"get_merge_modules iterates *.msm files in the merge-modules directory and derives each module's filename via Path::file_name(). If a matched path has no final component (ends in '..', root, or empty), file_name() returns None and the code panics with .expect(\"failed to extract merge module filename\").","triggerScenarios":"Calling bundle_project with bundle.windows.wix.mergeModules entries (or the resources/resources dir containing merge modules) where a glob-expanded path lacks a file name — e.g. a glob like \"dir/*\" matched nothing useful or the configured path ends in a separator or '..'.","commonSituations":"A merge module configured as a directory instead of an .msm file, a path with a trailing slash in tauri.conf.json, or a custom glob returning '.'/'..' entries.","solutions":["Point mergeModules at actual .msm files, not directories; remove trailing slashes and '..' components from the configured paths.","Check the merge-modules directory for odd entries (dot directories, symlinks to roots) and clean them.","Replace the expect with file_name().with_context(...)? or a filter_map that skips nameless paths."],"exampleFix":"// before\nlet filename = path.file_name().expect(\"failed to extract merge module filename\")\n  .to_os_string().into_string().expect(\"failed to convert merge module filename to string\");\n\n// after\nlet filename = path.file_name()\n  .with_context(|| format!(\"merge module path has no filename: {}\", path.display()))?\n  .to_string_lossy().into_owned();","handlingStrategy":"validation","validationCode":"// pre-scan merge module dir\nfor entry in glob(\"**/*.msm\")? {\n  let p = entry?;\n  if p.file_name().is_none() {\n    return Err(anyhow!(\"bad merge module path: {}\", p.display()));\n  }\n}","typeGuard":"fn has_filename(p: &std::path::Path) -> bool { p.file_name().is_some() }","tryCatchPattern":"// wrap the bundler in a subprocess; on this panic, report that a mergeModules\n// path is malformed (trailing slash, '..', or a directory).","preventionTips":["Configure mergeModules as concrete .msm files, not directories","Avoid trailing separators and '..' in configured paths","Sanitize downloaded merge modules (rename to ASCII, place in a clean dir)"],"tags":["msi","wix","windows","path","merge-module"],"backgroundTag":"path-has-no-filename","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"}