{"record":{"id":"b040fccef6b8079e","repo":"Tencent/matrix","slug":"debugging-apk-must-be-debuggable","errorCode":null,"errorMessage":"Debugging APK must be debuggable.","messagePattern":"Debugging APK must be debuggable\\.","errorType":"console","errorClass":"GradleScriptException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/gradle/WeChatDebugStub2.gradle","lineNumber":73,"sourceCode":"        Math.max(debugApk.lastModified(), debugStubPropFile.lastModified())) {\n    // Find ABIs to be installed\n    def zf = new ZipFile(debugApk)\n    zf.entries().each {\n        def m = (it.name =~ /^lib\\/([\\w-]+)\\//)\n        if (m) installAbis << m.group(1)\n    }\n    if (installAbis.empty) {\n        installAbis.addAll ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']\n    }\n\n    // Parse AndroidManifest.xml\n    def xmlRoot = new XmlSlurper().parseText(new ApkFile(debugApk).manifestXml)\n    xmlRoot.declareNamespace(android: 'http://schemas.android.com/apk/res/android')\n\n    // Check the debuggable flag.\n    def debuggable = xmlRoot.'application'[0].'@android:debuggable'.toString() as boolean\n    if (!debuggable) {\n        throw new GradleScriptException('Debugging APK must be debuggable.')\n    }\n\n    // Grab and define the min and target SDK level, then delete the <uses-sdk> node.\n    def useSdkNode = xmlRoot.'uses-sdk'[0]\n    minSdk = useSdkNode.'@android:minSdkVersion'.toString() as Integer\n    targetSdk = useSdkNode.'@android:targetSdkVersion'.toString() as Integer\n\n    // Grab package, application, default activity.\n    def packageName = xmlRoot.'@package' as String\n    def applicationName = xmlRoot.'application'[0].'@android:name' as String\n    def defaultActivityName = xmlRoot.'application'[0].activity.find { activity ->\n        activity.'intent-filter'.find { filter ->\n            filter.action[0].'@android:name' as String == 'android.intent.action.MAIN'\n        }\n    }.'@android:name' as String\n\n    // Write manifest and properties files.\n    Properties prop = new Properties()","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/gradle/WeChatDebugStub2.gradle#L55-L91","documentation":"The script parses the debug APK's AndroidManifest and requires android:debuggable to be true, because the debug-stub mechanism injects and hot-swaps code into a debuggable process. A release/non-debuggable APK fails with GradleScriptException.","triggerScenarios":"Pointing the apk= property at a release build (minifyEnabled/release signing) whose manifest lacks android:debuggable=true.","commonSituations":"Using the release APK instead of the debug variant; a build type where debuggable false was set explicitly; CI artifacts built with debuggable disabled.","solutions":["Use the debug variant APK (assembleDebug output) which is debuggable by default","Set debuggable true in the build type used to produce the APK","Re-verify the manifest after rebuilding before rerunning the task"],"exampleFix":"// before\nbuildTypes { release { debuggable false } }\napk=app/build/outputs/apk/release/app-release.apk\n// after\nbuildTypes { debug { debuggable true } }\napk=app/build/outputs/apk/debug/app-debug.apk","handlingStrategy":"validation","validationCode":"def isDebug = gradle.startParameter.taskNames.any { it.contains('Debug') }\nassert isDebug : 'Provide a debuggable APK to the debug-stub task'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always feed the debug variant APK to the script","Keep debuggable true in the debug build type","Verify manifest debuggable flag after building"],"tags":["gradle","android","debuggable","apk","validation"],"backgroundTag":"invalid-argument-value","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}