{"record":{"id":"33f631b42ad93d26","repo":"tauri-apps/tauri","slug":"permission-already-exists-at","errorCode":null,"errorMessage":"Permission already exists at {}","messagePattern":"Permission already exists at (.+?)","errorType":"exception","errorClass":"Error::GenericError","httpStatus":null,"severity":"error","filePath":"crates/tauri-cli/src/acl/permission/new.rs","lineNumber":97,"sourceCode":"      let permissions_dir = dir.join(\"permissions\");\n      permissions_dir.join(format!(\n        \"{}.{}\",\n        permission.identifier,\n        options.format.extension()\n      ))\n    }\n  };\n\n  if path.exists() {\n    let msg = format!(\n      \"Permission already exists at {}\",\n      dunce::simplified(&path).display()\n    );\n    let overwrite = prompts::confirm(&format!(\"{msg}, overwrite?\"), Some(false))?;\n    if overwrite {\n      std::fs::remove_file(&path).fs_context(\"failed to remove permission file\", path.clone())?;\n    } else {\n      crate::error::bail!(msg);\n    }\n  }\n\n  if let Some(parent) = path.parent() {\n    std::fs::create_dir_all(parent).fs_context(\n      \"failed to create permission directory\",\n      parent.to_path_buf(),\n    )?;\n  }\n\n  std::fs::write(\n    &path,\n    options\n      .format\n      .serialize(&PermissionFile {\n        default: None,\n        set: Vec::new(),\n        permission: vec![permission],","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/tauri-apps/tauri/blob/52e4b6e71d8632a7e648f866c442e287ecddee34/crates/tauri-cli/src/acl/permission/new.rs#L79-L115","documentation":"`tauri permission new` computes the target permission file path; if a file already exists there, the CLI asks `overwrite?` (defaulting to No). Declining the prompt — or answering No in a non-interactive context — aborts with the path that collided.","triggerScenarios":"Running `tauri permission new` with an identifier/outlet that maps to an already existing file (e.g. creating `fs:read-custom` twice, or two permissions whose identifiers slugify to the same filename) and answering No (or letting the default No apply) to the overwrite prompt.","commonSituations":"Regenerating a permission after editing it by hand and not wanting to lose changes; rerunning a scaffolding script that is not idempotent; permission identifiers that differ only by characters dropped during filename generation.","solutions":["Choose a different, unused permission identifier when creating the new permission","Answer Yes to the overwrite prompt if regenerating is intended (existing file is removed and rewritten)","Delete or rename the existing file yourself before re-running the command"],"exampleFix":"# before\ntauri permission new  # -> identifier: read-custom  (file already exists, answered No)\n\n# after\ntauri permission new  # -> identifier: read-custom-v2","handlingStrategy":"validation","validationCode":"// before scaffolding, check the target permission file is free\nimport { access } from 'node:fs/promises';\nconst p = 'src-tauri/permissions/my-plugin/read-custom.toml';\ntry { await access(p); console.error(`${p} already exists — pick a new identifier`); process.exit(1); }\ncatch { /* free to create */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use unique, descriptive permission identifiers so filename collisions cannot happen","Never hand-edit a scaffolded permission and then re-scaffold over it — answer No and edit instead","Make scaffolding scripts idempotent: check file existence before calling `tauri permission new`"],"tags":["tauri-cli","acl","permissions","file-conflict","interactive-prompt"],"backgroundTag":"file-already-exists","analyzedSha":"52e4b6e71d8632a7e648f866c442e287ecddee34","analyzedAt":"2026-08-20T13:59:20.734Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}