apache/cordova-android · error · CordovaError
Required attribute "target-dir" not specified in <source-fil
Error message
Required attribute "target-dir" not specified in <source-file> element from plugin: ${plugin.id} What it means
The second validation in the 'source-file' installer: after src is present, the element must also declare target-dir, which decides the destination path inside the Android project (getInstallDestination builds it from target-dir). Thrown during plugin install when target-dir is missing or empty.
Source
Thrown at lib/pluginHandlers.js:30
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
const fs = require('node:fs');
const path = require('node:path');
const isPathInside = require('is-path-inside');
const events = require('cordova-common').events;
const CordovaError = require('cordova-common').CordovaError;
const handlers = {
'source-file': {
install: function (obj, plugin, project, options) {
if (!obj.src) throw new CordovaError(generateAttributeError('src', 'source-file', plugin.id));
if (!obj.targetDir) throw new CordovaError(generateAttributeError('target-dir', 'source-file', plugin.id));
const dest = getInstallDestination(obj);
if (options && options.force) {
copyFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
} else {
copyNewFile(plugin.dir, obj.src, project.projectDir, dest, !!(options && options.link));
}
},
uninstall: function (obj, plugin, project, options) {
const dest = getInstallDestination(obj);
// TODO: Add Koltin extension to uninstall, since they are handled like Java files
if (obj.src.endsWith('java')) {
deleteJava(project.projectDir, dest);
} else {
// Just remove the file, not the whole parent directory
removeFileF(path.resolve(project.projectDir, dest));View on GitHub (pinned to 7c1e190064)
Solutions
- Add target-dir naming the destination under the Android project: <source-file src="src/android/Foo.java" target-dir="src/com/example/foo" />.
- Use the conventional location matching the Java package (src/<package path>) so the sources compile.
- If the file is a resource rather than compiled source, move it to a <resource-file> element targeting a res/ or assets/ directory instead.
- Patch or pin the offending third-party plugin.
Example fix
<!-- before --> <source-file src="src/android/Foo.java" /> <!-- after --> <source-file src="src/android/Foo.java" target-dir="src/com/example/foo" />
Defensive patterns
Strategy: validation
Validate before calling
const et = require('elementtree');
const pluginXml = et.parse(fs.readFileSync('plugin.xml', 'utf8').toString());
for (const el of pluginXml.getroot().iter('source-file')) {
if (!el.attrib['target-dir']) {
throw new Error(`<source-file src="${el.attrib.src}"> is missing target-dir="..."`);
}
} Type guard
const isValidSourceFileElement = (el) => Boolean(el && el.tag === 'source-file' && el.attrib && el.attrib.src && el.attrib['target-dir']);
Try / catch
try {
await api.addPlugin(pluginInfo);
} catch (e) {
if (/Required attribute "target-dir" not specified in <source-file>/.test(e.message)) {
// add target-dir matching the Java package path, e.g. src/com/example, then retry
}
throw e;
} Prevention
- Always pair src with target-dir on <source-file>; use the Java package path (src/<package>) as the destination.
- Use <resource-file> for non-compiled assets so target-dir is not required.
- Lint plugin.xml for required attributes in the plugin's CI.
When it happens
Trigger: `cordova plugin add <plugin>` where plugin.xml has <source-file src="..."/> with no target-dir attribute - the src check passes, then this one fires.
Common situations: Plugin authors assuming a default destination exists (there is none - the copy needs an explicit target); partial migration of an old plugin.xml; elements copied from <resource-file> which does not require target-dir.
Related errors
- Required attribute "src" not specified in <source-file> elem
- 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!
AI-assisted analysis of apache/cordova-android@7c1e190064 (2026-08-22).
Data as JSON: /api/errors/61654b6ba9f62ea0.
Report an issue: GitHub.