Tencent/matrix · error · GradleException

need sign apk but apksigner $apksigner was not exist!

Error message

need sign apk but apksigner $apksigner was not exist!

What it means

This variant of the signing configuration check fires when an `apksigner` path WAS provided but the file does not exist on disk. The task verifies `File(apksigner).exists()` before signing the shrunk APK and fails fast with the configured path included in the message.

Solutions

  1. Point `apksigner` at an existing build-tools binary on the current machine: `$ANDROID_HOME/build-tools/<version>/apksigner` (apksigner.bat on Windows).
  2. Run `ls` on the configured path to confirm it exists and is executable; update the config.
  3. Install the required build-tools version via the Android SDK manager if it is missing.
  4. Or set `needSign = false` if re-signing is not needed.

Example fix

// before
apksigner = "/Users/alice/Library/Android/sdk/build-tools/28.0.3/apksigner" // deleted by SDK upgrade

// after (check existing version first)
apksigner = "/Users/alice/Library/Android/sdk/build-tools/34.0.0/apksigner"
Defensive patterns

Strategy: validation

Validate before calling

def apksigner = new File("${System.getenv('ANDROID_HOME')}/build-tools/34.0.0/apksigner")
assert apksigner.exists() : "apksigner missing at ${apksigner}"

Type guard

def apksignerExists = { String p -> p != null && new File(p).exists() }

Try / catch

try { ... } catch (GradleException e) { if (e.message.contains('was not exist')) { logger.error('Fix apksigner path: ' + e.message) } throw e }

Prevention

When it happens

Trigger: `needSign = true`, `apksigner` is a non-empty string, but `File(apksigner).exists()` returns false when `removeUnusedResources` executes.

Common situations: Hard-coded path from another machine or CI image; SDK upgraded and the old build-tools directory was deleted; relative path resolved against a different working directory; typo in path or missing executable extension on Windows.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at matrix/matrix-android/matrix-gradle-plugin/src/main/kotlin/com/tencent/matrix/plugin/task/RemoveUnusedResourcesTask.kt:130

                    typeName = typeName.substring(0, index)
                }
                resourceName = "R.$typeName.$resName"
            }
        }
        return resourceName
    }

    private fun removeUnusedResources(
            originalApk: String,
            rTxtFile: String,
            signingConfig: SigningConfig?) {

        // Check configurations
        if (needSign) {
            if (Util.isNullOrNil(apksigner)) {
                throw GradleException("need sign apk but apksigner not found!");
            } else if (!File(apksigner).exists()) {
                throw GradleException("need sign apk but apksigner $apksigner was not exist!");
            } else if (signingConfig == null) {
                throw GradleException("need sign apk but signingConfig not found!");
            }
        }

        var zipOutputStream: ZipOutputStream? = null

        try {
            try {
                val inputFile = File(originalApk)

                for (res in ignoreRes) {
                    ignoreResources.add(Util.globToRegexp(res))
                }

                val iterator = unusedResources.iterator()
                while (iterator.hasNext()) {
                    val res = iterator.next()

View on GitHub (pinned to 3b8293bd65)