Tencent/matrix · error · GradleScriptException

Debugging APK must be debuggable.

Error message

Debugging APK must be debuggable.

What it means

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.

Solutions

  1. Use the debug variant APK (assembleDebug output) which is debuggable by default
  2. Set debuggable true in the build type used to produce the APK
  3. Re-verify the manifest after rebuilding before rerunning the task

Example fix

// before
buildTypes { release { debuggable false } }
apk=app/build/outputs/apk/release/app-release.apk
// after
buildTypes { debug { debuggable true } }
apk=app/build/outputs/apk/debug/app-debug.apk
Defensive patterns

Strategy: validation

Validate before calling

def isDebug = gradle.startParameter.taskNames.any { it.contains('Debug') }
assert isDebug : 'Provide a debuggable APK to the debug-stub task'

Prevention

When it happens

Trigger: Pointing the apk= property at a release build (minifyEnabled/release signing) whose manifest lacks android:debuggable=true.

Common situations: Using the release APK instead of the debug variant; a build type where debuggable false was set explicitly; CI artifacts built with debuggable disabled.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08). Data as JSON: /api/errors/b040fccef6b8079e. Report an issue: GitHub.

Appendix: source

Thrown at matrix/matrix-android/gradle/WeChatDebugStub2.gradle:73

        Math.max(debugApk.lastModified(), debugStubPropFile.lastModified())) {
    // Find ABIs to be installed
    def zf = new ZipFile(debugApk)
    zf.entries().each {
        def m = (it.name =~ /^lib\/([\w-]+)\//)
        if (m) installAbis << m.group(1)
    }
    if (installAbis.empty) {
        installAbis.addAll ['armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64']
    }

    // Parse AndroidManifest.xml
    def xmlRoot = new XmlSlurper().parseText(new ApkFile(debugApk).manifestXml)
    xmlRoot.declareNamespace(android: 'http://schemas.android.com/apk/res/android')

    // Check the debuggable flag.
    def debuggable = xmlRoot.'application'[0].'@android:debuggable'.toString() as boolean
    if (!debuggable) {
        throw new GradleScriptException('Debugging APK must be debuggable.')
    }

    // Grab and define the min and target SDK level, then delete the <uses-sdk> node.
    def useSdkNode = xmlRoot.'uses-sdk'[0]
    minSdk = useSdkNode.'@android:minSdkVersion'.toString() as Integer
    targetSdk = useSdkNode.'@android:targetSdkVersion'.toString() as Integer

    // Grab package, application, default activity.
    def packageName = xmlRoot.'@package' as String
    def applicationName = xmlRoot.'application'[0].'@android:name' as String
    def defaultActivityName = xmlRoot.'application'[0].activity.find { activity ->
        activity.'intent-filter'.find { filter ->
            filter.action[0].'@android:name' as String == 'android.intent.action.MAIN'
        }
    }.'@android:name' as String

    // Write manifest and properties files.
    Properties prop = new Properties()

View on GitHub (pinned to 3b8293bd65)