{"record":{"id":"25ed4a3975e3b627","repo":"Tencent/matrix","slug":"need-sign-apk-but-apksigner-not-found","errorCode":null,"errorMessage":"need sign apk but apksigner not found!","messagePattern":"need sign apk but apksigner not found!","errorType":"exception","errorClass":"GradleException","httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-gradle-plugin/src/main/kotlin/com/tencent/matrix/plugin/task/RemoveUnusedResourcesTask.kt","lineNumber":128,"sourceCode":"                val index = typeName.indexOf('-')\n                if (index >= 0) {\n                    typeName = typeName.substring(0, index)\n                }\n                resourceName = \"R.$typeName.$resName\"\n            }\n        }\n        return resourceName\n    }\n\n    private fun removeUnusedResources(\n            originalApk: String,\n            rTxtFile: String,\n            signingConfig: SigningConfig?) {\n\n        // Check configurations\n        if (needSign) {\n            if (Util.isNullOrNil(apksigner)) {\n                throw GradleException(\"need sign apk but apksigner not found!\");\n            } else if (!File(apksigner).exists()) {\n                throw GradleException(\"need sign apk but apksigner $apksigner was not exist!\");\n            } else if (signingConfig == null) {\n                throw GradleException(\"need sign apk but signingConfig not found!\");\n            }\n        }\n\n        var zipOutputStream: ZipOutputStream? = null\n\n        try {\n            try {\n                val inputFile = File(originalApk)\n\n                for (res in ignoreRes) {\n                    ignoreResources.add(Util.globToRegexp(res))\n                }\n\n                val iterator = unusedResources.iterator()","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-gradle-plugin/src/main/kotlin/com/tencent/matrix/plugin/task/RemoveUnusedResourcesTask.kt#L110-L146","documentation":"When `removeUnusedResources` is configured to re-sign the processed APK (`needSign = true`), the task must run apksigner to sign the rebuilt APK. This error is thrown when the configured `apksigner` value is null or empty, meaning no signer tool path was provided at all. It is a fail-fast configuration check performed before any work is done.","triggerScenarios":"`needSign` is true but the extension's `apksigner` property was never set (empty/null) when `removeUnusedResources` runs via `removeResources`.","commonSituations":"Enabling signing in matrixTrace/matrix config without pointing `apksigner` at `<Android SDK>/build-tools/<version>/apksigner`; using defaults on a machine without Android build-tools; copying sample config that omits the field.","solutions":["Set `apksigner` in the matrix removeUnusedResources extension to the full path of the apksigner binary, e.g. `$ANDROID_HOME/build-tools/34.0.0/apksigner`.","Verify build-tools are installed via the SDK manager and use that version's path.","If signing is handled elsewhere, disable it by setting `needSign = false` so the check is skipped."],"exampleFix":"// before\nmatrix {\n  removeUnusedResources {\n    needSign = true\n  }\n}\n\n// after\nmatrix {\n  removeUnusedResources {\n    needSign = true\n    apksigner = \"/opt/android-sdk/build-tools/34.0.0/apksigner\"\n  }\n}","handlingStrategy":"validation","validationCode":"def apksigner = \"/opt/android-sdk/build-tools/34.0.0/apksigner\"\nassert apksigner?.trim() : 'apksigner path must be set when needSign=true'\nmatrix { removeUnusedResources { needSign = true; apksigner = apksigner } }","typeGuard":"def hasApksigner = { String p -> p != null && !p.trim().isEmpty() }","tryCatchPattern":"try { matrixRemoveUnusedResources() } catch (GradleException e) { if (e.message.contains('apksigner not found')) { ... configure apksigner ... } else throw e }","preventionTips":["Always set apksigner alongside needSign = true.","Derive the path from ANDROID_HOME + build-tools version instead of hardcoding.","Verify signing needs before enabling needSign."],"tags":["gradle","android","signing","missing-config-value"],"backgroundTag":"missing-config-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"}