apache/cordova-android · error · CordovaError

Required attribute "src" not specified in <source-file> elem

Error message

Required attribute "src" not specified in <source-file> element from plugin: ${plugin.id}

What it means

The 'source-file' installer in pluginHandlers validates each <source-file> element of a plugin.xml before copying anything: it requires a src attribute (the file inside the plugin) and, next, a target-dir attribute. A missing/empty src throws immediately with the plugin id in the message. Raised during `cordova plugin add`.

Source

Thrown at lib/pluginHandlers.js:29

    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

View on GitHub (pinned to 7c1e190064)

Solutions

  1. Add src to the element, pointing at a file inside the plugin package: <source-file src="src/android/Foo.java" ...>.
  2. Verify the referenced file actually exists in the plugin directory.
  3. Also set target-dir (the very next validation) to the destination under the Android project, e.g. target-dir="src/com/example".
  4. If the plugin is third-party, pin a fixed release or patch it locally (cordova plugin add ./path --searchpath).

Example fix

<!-- before -->
<source-file target-dir="src/com/example/foo" />

<!-- 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.src) {
    throw new Error(`<source-file> in ${plugin.id} is missing src="..."`);
  }
}

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 ".*" not specified in <source-file>/.test(e.message)) {
    // fix the named attribute in the named plugin's plugin.xml, then retry plugin add
  }
  throw e;
}

Prevention

When it happens

Trigger: `cordova plugin add <plugin>` (or pluginManager install) where the plugin's plugin.xml contains <source-file> without src, e.g. `<source-file target-dir="src/com/example"/>` or src="".

Common situations: Hand-written or local plugins missing attributes; plugin.xml refactored and the src attribute dropped; a plugin element copy-pasted from a different platform's section.

Related errors


AI-assisted analysis of apache/cordova-android@7c1e190064 (2026-08-22). Data as JSON: /api/errors/008354ef004fa885. Report an issue: GitHub.