{"record":{"id":"5e1f5682450e2e71","repo":"apache/cordova-android","slug":"required-attribute-src-not-specified-in-asset","errorCode":null,"errorMessage":"Required attribute \"src\" not specified in <asset> element from plugin: ${plugin.id}","messagePattern":"Required attribute \"src\" not specified in <asset> element from plugin: (.+?)","errorType":"validation","errorClass":"CordovaError","httpStatus":null,"severity":"error","filePath":"lib/pluginHandlers.js","lineNumber":132,"sourceCode":"                }\n            } else {\n                obj.type = 'sys';\n                subDir = src;\n            }\n\n            if (obj.type === 'gradleReference') {\n                project.removeGradleReference(parentDir, subDir);\n            } else if (obj.type === 'sys') {\n                project.removeSystemLibrary(parentDir, subDir);\n            } else {\n                project.removeSubProject(parentDir, subDir);\n            }\n        }\n    },\n    asset: {\n        install: function (obj, plugin, project, options) {\n            if (!obj.src) {\n                throw new CordovaError(generateAttributeError('src', 'asset', plugin.id));\n            }\n            if (!obj.target) {\n                throw new CordovaError(generateAttributeError('target', 'asset', plugin.id));\n            }\n\n            copyFile(plugin.dir, obj.src, project.www, obj.target);\n            if (options && options.usePlatformWww) {\n                // CB-11022 copy file to both directories if usePlatformWww is specified\n                copyFile(plugin.dir, obj.src, project.platformWww, obj.target);\n            }\n        },\n        uninstall: function (obj, plugin, project, options) {\n            const target = obj.target || obj.src;\n\n            if (!target) {\n                throw new CordovaError(generateAttributeError('target', 'asset', plugin.id));\n            }\n","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/apache/cordova-android/blob/7c1e190064e349ffa4bbc6ac37b77cd773e4dbd3/lib/pluginHandlers.js#L114-L150","documentation":"Thrown by the asset install handler when a plugin's plugin.xml declares <asset> without a src attribute. <asset> copies a www-facing file (JS, CSS, images) from the plugin into the app's www tree, so the source path is mandatory; cordova-android aborts the plugin install when it is missing.","triggerScenarios":"`cordova plugin add <plugin>` where plugin.xml contains <asset target=\"www/foo.js\"/> (target present, src absent). The handler checks !obj.src first and throws generateAttributeError('src','asset',...).","commonSituations":"Typos such as <asset source=\"...\">; refactoring plugin.xml and deleting the src attribute; HTML/JS assets moved without updating plugin.xml.","solutions":["Add src to the <asset> element, relative to the plugin root: <asset src=\"www/foo.js\" target=\"www/foo.js\"/>","Verify the file actually exists at that path inside the plugin (see the separate '\"...\" not found!' error)","Fix upstream and republish the plugin if it ships broken"],"exampleFix":"<!-- before -->\n<asset target=\"www/cdv-plugin.js\" />\n\n<!-- after -->\n<asset src=\"www/cdv-plugin.js\" target=\"www/cdv-plugin.js\" />","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nconst xml = fs.readFileSync('node_modules/<plugin>/plugin.xml', 'utf8');\nif (/<asset(?![^>]*\\bsrc=)[^>]*\\/>/.test(xml)) {\n  throw new Error('<asset> without src — fix plugin.xml before install');\n}","typeGuard":null,"tryCatchPattern":"try { await cordova.plugin('add', p); } catch (e) {\n  if (/Required attribute \"src\" not specified in <asset>/.test(e.message)) { /* fix plugin.xml asset elements */ }\n}","preventionTips":["Author plugins with a plugin.xml schema check in CI","Use <asset src=... target=...> as a pair; treat one without the other as a bug"],"tags":["cordova","cordova-android","plugin-xml","asset","install"],"backgroundTag":"plugin-manifest-attribute-missing","analyzedSha":"7c1e190064e349ffa4bbc6ac37b77cd773e4dbd3","analyzedAt":"2026-08-22T04:57:58.868Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}