{"record":{"id":"d3b94250171d5429","repo":"apache/cordova-android","slug":"could-not-find-apk-architecture-arch-build-typ","errorCode":null,"errorMessage":"Could not find apk architecture: ${arch} build-type: ${buildResults.buildType}","messagePattern":"Could not find apk architecture: (.+?) build-type: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/build.js","lineNumber":230,"sourceCode":"        const apkName = path.basename(p);\n        if (buildResults.buildType === 'debug') {\n            return /-debug/.exec(apkName);\n        }\n        return !/-debug/.exec(apkName);\n    });\n    const archPattern = new RegExp('-' + arch);\n    const hasArchPattern = /-x86|-arm/;\n    for (let i = 0; i < paths.length; ++i) {\n        const apkName = path.basename(paths[i]);\n        if (hasArchPattern.exec(apkName)) {\n            if (archPattern.exec(apkName)) {\n                return paths[i];\n            }\n        } else {\n            return paths[i];\n        }\n    }\n    throw new Error('Could not find apk architecture: ' + arch + ' build-type: ' + buildResults.buildType);\n};\n\nfunction PackageInfo (keystore, alias, storePassword, password, keystoreType) {\n    const createNameKeyObject = (name, value) => ({ name, value: value.replace(/\\\\/g, '\\\\\\\\') });\n\n    this.data = [\n        createNameKeyObject('key.store', keystore),\n        createNameKeyObject('key.alias', alias)\n    ];\n\n    if (storePassword) this.data.push(createNameKeyObject('key.store.password', storePassword));\n    if (password) this.data.push(createNameKeyObject('key.alias.password', password));\n    if (keystoreType) this.data.push(createNameKeyObject('key.store.type', keystoreType));\n}\n\nPackageInfo.prototype = {\n    appendToProperties: function (propertiesParser) {\n        for (const { name, value } of this.data) propertiesParser.set(name, value);","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/apache/cordova-android/blob/7c1e190064e349ffa4bbc6ac37b77cd773e4dbd3/lib/build.js#L212-L248","documentation":"findBestApkForArchitecture(buildResults, arch) filters buildResults.apkPaths by build type (names containing '-debug' for debug builds, otherwise non-debug names), then walks the list: a file whose name contains -x86/-arm must match '-'+arch, while a name with no arch suffix is treated as universal and returned immediately. Thrown when, after the build-type filter, no remaining APK matches the requested architecture.","triggerScenarios":"The run/emulate flow detects the device arch via `Adb.shell(target, 'cat /proc/cpuinfo')` (/intel/ -> 'x86', else 'arm', lib/build.js:205-207) and calls this helper; it throws when the built APKs cover a different ABI, e.g. arch='x86' but only app-arm-debug.apk exists, or the '-debug' filter dropped every path because output names are nonstandard.","commonSituations":"Building with a single-ABI flag but deploying to the other ABI; stale apkPaths from a previous build after config changes; gradle output renaming (custom suffixes) breaking the -debug/-x86/-arm filename matching; build results containing no apks for the current buildType.","solutions":["Rebuild producing the needed ABI (or all ABIs) and verify the output filenames under platforms/android/app/build/outputs/apk/ contain '-<arch>' or no arch suffix.","Inspect buildResults.apkPaths before deploying: confirm at least one basename matches the current buildType filter and the target arch.","If you customize gradle output names, keep the standard '-debug'/'-release' and '-arm64-v8a'/'-x86'/'-x86_64' naming so the regex matching works.","Remove stale outputs: `cordova clean android`, then rebuild."],"exampleFix":"// before\nconst apk = build.findBestApkForArchitecture(buildResults, targetArch); // throws on ABI mismatch\n\n// after: pre-check, and prefer an exact-ABI apk with universal fallback\nconst names = buildResults.apkPaths.map(p => path.basename(p));\nconst apk = buildResults.apkPaths.find(p => path.basename(p).includes('-' + targetArch)) ||\n           buildResults.apkPaths.find(p => !/-x86|-arm/.test(path.basename(p)));\nif (!apk) throw new Error('No ' + targetArch + ' APK in: ' + names.join(', '));","handlingStrategy":"validation","validationCode":"const hasApkForArch = (buildResults, arch) =>\n  buildResults.apkPaths.some(p =>\n    new RegExp('-' + arch).test(path.basename(p)) || !/-x86|-arm/.test(path.basename(p))\n  );\n\nif (!hasApkForArch(buildResults, targetArch)) {\n  throw new Error(`Rebuild for ${targetArch}: available APKs are ${buildResults.apkPaths.join(', ')}`);\n}","typeGuard":"const isValidApkSet = (buildResults) =>\n  Array.isArray(buildResults.apkPaths) &&\n  buildResults.apkPaths.length > 0 &&\n  typeof buildResults.buildType === 'string' && /debug|release/.test(buildResults.buildType);","tryCatchPattern":"try {\n  apk = build.findBestApkForArchitecture(buildResults, targetArch);\n} catch (e) {\n  if (/Could not find apk architecture/.test(e.message)) {\n    // recover by building the missing ABI, then retry once\n    await androidApi.build({ ...opts, arch: [targetArch] });\n    apk = build.findBestApkForArchitecture(buildResults, targetArch);\n  } else throw e;\n}","preventionTips":["Build all ABIs you intend to deploy to instead of one, so any device arch finds a match.","Do not rename gradle APK outputs - the selector relies on '-debug' and '-x86'/'-arm' substrings.","Run `cordova clean android` when switching build type or ABI configurations."],"tags":["apk","abi","architecture","build-output","cordova-run"],"backgroundTag":"build-artifact-not-found","analyzedSha":"7c1e190064e349ffa4bbc6ac37b77cd773e4dbd3","analyzedAt":"2026-08-22T04:57:58.868Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}