apache/cordova-android · error · CordovaError
"${target_path}" already exists!
Error message
"${target_path}" already exists! What it means
copyNewFile (used for source-file, framework, etc. unless --force) refuses to overwrite: if the resolved destination already exists on disk it throws. It prevents a plugin install from silently clobbering files that already exist in the Android project, which usually means the plugin (or an older version of it) was installed before and not fully removed.
Source
Thrown at lib/pluginHandlers.js:233
if (!isPathInside(real_path, real_plugin_path)) { throw new CordovaError('File "' + src + '" is located outside the plugin directory "' + plugin_dir + '"'); }
dest = path.resolve(project_dir, dest);
// check that dest path is located in project directory
if (!isPathInside(dest, project_dir)) { throw new CordovaError('Destination "' + dest + '" for source file "' + src + '" is located outside the project'); }
fs.mkdirSync(path.dirname(dest), { recursive: true });
if (link) {
symlinkFileOrDirTree(src, dest);
} else {
fs.cpSync(src, dest, { recursive: true });
}
}
// Same as copy file but throws error if target exists
function copyNewFile (plugin_dir, src, project_dir, dest, link) {
const target_path = path.resolve(project_dir, dest);
if (fs.existsSync(target_path)) { throw new CordovaError('"' + target_path + '" already exists!'); }
copyFile(plugin_dir, src, project_dir, dest, !!link);
}
function symlinkFileOrDirTree (src, dest) {
if (fs.existsSync(dest)) {
fs.rmSync(dest, { recursive: true, force: true });
}
if (fs.statSync(src).isDirectory()) {
fs.mkdirSync(path.dirname(dest), { recursive: true });
fs.readdirSync(src).forEach(function (entry) {
symlinkFileOrDirTree(path.join(src, entry), path.join(dest, entry));
});
} else {
fs.symlinkSync(path.relative(fs.realpathSync(path.dirname(dest)), src), dest);
}
}View on GitHub (pinned to 7c1e190064)
Solutions
- Remove the plugin cleanly first (`cordova plugin rm <id>`), delete any leftover target files it reports, then re-add
- Regenerate the platform if state is uncertain: `cordova platform rm android && cordova platform add android`
- Intentional overwrite? re-add with `cordova plugin add <id> --force` so copyFile is used instead of copyNewFile
- For your own plugin, give shared/generic files a namespaced target path (e.g. target-dir includes your package name) to avoid collisions with other plugins
Example fix
# before cordova plugin add cordova-plugin-foo # throws: file already exists # after cordova plugin rm cordova-plugin-foo cordova platform rm android && cordova platform add android cordova plugin add cordova-plugin-foo # or, to allow overwriting: cordova plugin add cordova-plugin-foo --force
Defensive patterns
Strategy: fallback
Validate before calling
// pre-flight: check whether the plugin's source-file targets already exist
const fs = require('fs'); const path = require('path');
const projectDir = 'platforms/android';
const exists = fs.existsSync(path.resolve(projectDir, targetDirAttr, path.basename(srcAttr)));
// if exists, choose --force or clean up leftovers before installing Try / catch
try { await cordova.plugin('add', p); } catch (e) {
if (/already exists!/.test(e.message)) { /* rm plugin / regenerate platform, or re-add with --force */ }
} Prevention
- Always `cordova plugin rm` before manually touching plugin files
- When a plugin fails mid-install, remove it fully before retrying
- Namespace target-dir with your package name to avoid collisions
- Use `--force` only when overwriting is intentional
When it happens
Trigger: `cordova plugin add` for a plugin whose <source-file> target path already exists: e.g. plugin added twice, a previous uninstall left files behind, or two plugins shipping a file with the same target-dir and name. Not thrown for resource-file/asset (those use plain copyFile and overwrite) nor when options.force is set.
Common situations: Re-adding a plugin after a failed uninstall or manual surgery on platforms/; upgrading a plugin whose files changed location; two plugins bundling the same support library source file; stale platforms/ directory after switching branches.
Related errors
- Required attribute "src" not specified in <framework> elemen
- Required attribute "src" not specified in <asset> element fr
- Required attribute "target" not specified in <asset> element
- "${src}" not found!
- File "${src}" is located outside the plugin directory "${plu
AI-assisted analysis of apache/cordova-android@7c1e190064 (2026-08-22).
Data as JSON: /api/errors/9c3357e59c117185.
Report an issue: GitHub.