{"record":{"id":"c51e3a1d112754d6","repo":"tauri-apps/tauri","slug":"failed-to-create-plugin-documentation-directory","errorCode":null,"errorMessage":"failed to create plugin documentation directory","messagePattern":"failed to create plugin documentation directory","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tauri/build.rs","lineNumber":433,"sourceCode":"      .unwrap_or_else(|_| panic!(\"unable to autogenerate default permissions\"));\n\n    let permissions = tauri_utils::acl::build::define_permissions(\n      &PathBuf::from(glob::Pattern::escape(\n        &permissions_out_dir.to_string_lossy(),\n      ))\n      .join(\"**\")\n      .join(\"*.toml\")\n      .to_string_lossy(),\n      &format!(\"tauri:{plugin}\"),\n      out_dir,\n      |_| true,\n    )\n    .unwrap_or_else(|e| panic!(\"failed to define permissions for {plugin}: {e}\"));\n\n    let docs_out_dir = Path::new(\"permissions\")\n      .join(plugin_directory_name)\n      .join(\"autogenerated\");\n    fs::create_dir_all(&docs_out_dir).expect(\"failed to create plugin documentation directory\");\n    tauri_utils::acl::build::generate_docs(\n      &permissions,\n      &docs_out_dir,\n      plugin.strip_prefix(\"tauri-plugin-\").unwrap_or(plugin),\n    )\n    .expect(\"failed to generate plugin documentation page\");\n    all_permissions.insert(plugin.to_string(), permissions);\n  }\n\n  let default_permissions = define_default_permission_set(out_dir);\n  all_permissions.insert(\"core\".to_string(), default_permissions);\n\n  all_permissions\n}\n\nfn define_default_permission_set(\n  out_dir: &Path,\n) -> Vec<tauri_utils::acl::manifest::PermissionFile> {","sourceCodeStart":415,"sourceCodeEnd":451,"githubUrl":"https://github.com/tauri-apps/tauri/blob/52e4b6e71d8632a7e648f866c442e287ecddee34/crates/tauri/build.rs#L415-L451","documentation":"For each first-party plugin, the tauri build script generates ACL permission docs into permissions/<plugin>/autogenerated under the crate. The expect fires when fs::create_dir_all fails: a regular file already exists at that path (or a parent of it), or the filesystem denies directory creation.","triggerScenarios":"A file (not a directory) checked in at permissions/<plugin> or permissions/<plugin>/autogenerated in the plugin crate; building from a read-only source tree (e.g. files owned by root from previous sudo builds).","commonSituations":"Leftover artifacts committed by mistake; sudo-built directories now unwritable; read-only CI checkouts where docs are written into the source tree.","solutions":["Inspect permissions/<plugin>/autogenerated in the offending crate: remove any file occupying that path so a directory can be created.","Fix ownership/permissions of the source tree (e.g. chown after sudo builds).","Build in an environment that permits writing to the source directory."],"exampleFix":"# before: a regular file occupies the path\npermissions/my-plugin/autogenerated  # <- file\nrm permissions/my-plugin/autogenerated\n\n# after: build recreates it as a directory","handlingStrategy":"validation","validationCode":"let docs = std::path::Path::new(\"permissions\").join(plugin_dir).join(\"autogenerated\");\nif docs.exists() && !docs.is_dir() {\n    panic!(\"{} is a file; remove it so the docs directory can be created\", docs.display());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never commit a file where permissions/<plugin>/autogenerated must live.","Avoid sudo builds that leave root-owned files in the source tree.","Keep source checkouts writable when building plugins in-tree."],"tags":["tauri","build-script","acl","permissions","filesystem"],"backgroundTag":"file-directory-conflict","analyzedSha":"52e4b6e71d8632a7e648f866c442e287ecddee34","analyzedAt":"2026-08-20T13:59:20.734Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}