Skip to content

Keystore file not found for signing config 'externalOverride' #20

@janodetzel

Description

@janodetzel

Keystore file not found for signing config 'externalOverride'

When running Rock Remote Build - Android with sign: true, the build fails because the Android Gradle Plugin (AGP) cannot find the keystore file. It looks for it in the Gradle daemon directory instead of where the action actually places it.

Error from logs

> Keystore file '/home/runner/.gradle/daemon/9.0.0/release.keystore' not found for signing config 'externalOverride'.

The exact daemon path may vary (e.g. 9.0.0 depends on the Gradle version). The filename (release.keystore) comes from the keystore-store-file input.

Steps to reproduce

  1. Use the Rock Remote Build - Android action with signing enabled:

    • sign: true
    • keystore-base64 (or keystore-file) and keystore-store-file (e.g. release.keystore) set
    • keystore-store-password, keystore-key-alias, keystore-key-password set
    • keystore-path not set explicitly (default release.keystore is used)
  2. Run the workflow.

  3. The "Build Android" step fails with the error above.

Expected behavior

The build should succeed and produce a signed APK/AAB. The keystore is decoded and written by the "Decode and store keystore" step to a path like android/app/release.keystore (or $ANDROID_SOURCE_DIR/$APP_NAME/release.keystore). AGP should use that file for the externalOverride signing config.

Actual behavior

AGP resolves android.injected.signing.store.file as a path. When it receives a relative value (e.g. release.keystore), it resolves it from the Gradle daemon working directory (e.g. /home/runner/.gradle/daemon/9.0.0/), so it tries to open:

  • /home/runner/.gradle/daemon/9.0.0/release.keystore

That file does not exist. The real keystore is at e.g.:

  • $GITHUB_WORKSPACE/android/app/release.keystore (or similar, depending on keystore-path and project layout).

Root cause

  1. The action writes android.injected.signing.* properties to $HOME/.gradle/gradle.properties. AGP reads these and creates an externalOverride signing config.

  2. For android.injected.signing.store.file, the action was writing the bare filename from the keystore-store-file input (e.g. release.keystore), not the full path where the keystore is stored.

  3. AGP treats android.injected.signing.store.file as a path. For relative values, it resolves them from the Gradle daemon directory, not from the project or android/app/.

  4. Relative path + wrong base directory → "Keystore file not found" for externalOverride.

The action also sets ROCK_UPLOAD_STORE_FILE and similar; apps using file(ROCK_UPLOAD_STORE_FILE) in build.gradle can resolve correctly relative to the project. However, android.injected.signing.* takes precedence, so AGP uses externalOverride with the wrong path.
So commenting out the android.injected.signing.* parts also fixes the problem for me.

Suggested fix

  1. Run "Create local gradle.properties" after "Decode and store keystore" so the absolute path (KEYSTORE_TARGET_PATH) is available when writing gradle.properties.

  2. Set android.injected.signing.store.file to that absolute path instead of the filename:

    android.injected.signing.store.file=$KEYSTORE_TARGET_PATH
    

    KEYSTORE_TARGET_PATH is the absolute path produced by the "Decode and store keystore" step (e.g. /home/runner/work/.../android/app/release.keystore).

  3. Leave android.injected.signing.store.password, key.alias, key.password, and all ROCK_UPLOAD_* properties unchanged.

With an absolute path, AGP’s externalOverride finds the keystore correctly. No changes are required in build.gradle or app code.

Environment

  • Action: Rock Remote Build - Android (composite action)
  • Trigger: sign: true with valid keystore inputs
  • Runner: GitHub-hosted (e.g. ubuntu-latest); the daemon path is under /home/runner/.gradle/daemon/
  • AGP: reads android.injected.signing.* from ~/.gradle/gradle.properties and creates externalOverride signing config

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions