{"record":{"id":"77470e86b8061ef7","repo":"tauri-apps/tauri","slug":"embedded-file-asset-has-no-parent","errorCode":null,"errorMessage":"embedded file asset has no parent","messagePattern":"embedded file asset has no parent","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tauri-codegen/src/embedded_assets.rs","lineNumber":117,"sourceCode":"  paths: Vec<(PathBuf, DirEntry)>,\n  csp_hashes: CspHashes,\n}\n\nimpl RawEmbeddedAssets {\n  /// Creates a new list of (prefix, entry) from a collection of inputs.\n  fn new(input: EmbeddedAssetsInput, options: &AssetOptions) -> Result<Self, EmbeddedAssetsError> {\n    let mut csp_hashes = CspHashes::default();\n\n    input\n      .0\n      .into_iter()\n      .flat_map(|path| {\n        let prefix = if path.is_dir() {\n          path.clone()\n        } else {\n          path\n            .parent()\n            .expect(\"embedded file asset has no parent\")\n            .to_path_buf()\n        };\n\n        WalkDir::new(&path)\n          .follow_links(true)\n          .contents_first(true)\n          .into_iter()\n          .map(move |entry| (prefix.clone(), entry))\n      })\n      .filter_map(|(prefix, entry)| {\n        match entry {\n          // we only serve files, not directory listings\n          Ok(entry) if entry.file_type().is_dir() => None,\n\n          // compress all files encountered\n          Ok(entry) => {\n            if let Err(error) = csp_hashes\n              .add_if_applicable(&entry, &options.dangerous_disable_asset_csp_modification)","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/tauri-apps/tauri/blob/52e4b6e71d8632a7e648f866c442e287ecddee34/crates/tauri-codegen/src/embedded_assets.rs#L99-L135","documentation":"Build-time panic in tauri-codegen's embedded-assets pass: for every configured asset path that is a file, it takes path.parent().expect(\"embedded file asset has no parent\"). Path::parent() returns None only for degenerate paths — empty string, \"/\", or a prefix ending at the root — so the panic means an entry in the assets input (e.g. the frontendDist list) is empty or root-like instead of a real file/directory.","triggerScenarios":"tauri.conf.json `build > frontendDist` (or custom asset paths passed to generate_context!) containing an entry like \"\", \"/\", or a path whose parent is the filesystem root — e.g. \"frontendDist\": [\"\", \"../dist\"], or a template variable that expands to an empty string in CI.","commonSituations":"Config templating that leaves an empty asset path when an environment variable is unset; glob expansion producing an empty element; hand-editing the frontendDist array.","solutions":["Inspect the effective config (`tauri build --verbose` prints it) and remove empty or root entries from frontendDist / asset path lists","Default the variable so the entry is never empty, e.g. \"${FRONTEND_DIST:-../dist}\"","After fixing the config, cargo clean or touch build.rs so codegen re-runs with the corrected paths"],"exampleFix":"// tauri.conf.json — before\n\"build\": { \"frontendDist\": [\"${FRONTEND_DIST}\"] }  // empty in CI\n\n// after\n\"build\": { \"frontendDist\": [\"../dist\"] }","handlingStrategy":"validation","validationCode":"# config lint: frontendDist must be a non-empty string or an array of non-empty, non-root paths\njq -e '.build.frontendDist | if type == \"array\" then all(length > 0 and . != \"/\") else (type == \"string\" and length > 0) end' src-tauri/tauri.conf.json","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default every templated config variable so it can never expand empty","Lint tauri.conf.json in CI with jq before building","Keep asset path entries relative to the config file and never root-like"],"tags":["assets","config","path","codegen"],"backgroundTag":"invalid-asset-path","analyzedSha":"52e4b6e71d8632a7e648f866c442e287ecddee34","analyzedAt":"2026-08-20T13:59:20.734Z","contentChangedAt":"2026-08-20T13:59:20.734Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}