EAS Build claims to use correct keystore in logs but produces incorrectly signed Android builds during submission
- Dominant language
- TypeScript
- Stars
- 1.4k
- Forks
- 236
- Avg merge
- 3d 8h
- Merged PRs (30d)
- 98
Description
### Build/Submit details page URL
https://expo.dev/accounts/y-m2000/projects/hoy/submissions/64efd093-de88-41ad-88f3-295653c81d4f
### Summary
EAS Build consistently reports using the correct Android keystore in build logs ("Using Keystore from configuration: y-m2000"), but the generated .aab files are signed with an unexpected debug keystore. This is causing Google Play Store submission failures with "All uploaded bundles must be signed" or "signed with the wrong key" errors.
### Managed or bare?
Managed (transitioned to bare during debugging by committing android/ folder to override EAS prebuild)
### Environment
System:
OS: Windows 11
Node: 22.17.1
npm: 11.4.2
Expo CLI: @expo/cli@0.21.x
EAS CLI: eas-cli@16.17.3
React Native: 0.79.5
Expo SDK: 53.0.20
### Error output
```
Starting the submit process
Downloading archive
Preparing artifact
Submitting Android app to Play Store...
Submitting the app with fastlane supply
+-------------------------------------------------------------------------------------------------------------------------------------------------+
| Summary for supply 2.220.0 |
+------------------------------------+------------------------------------------------------------------------------------------------------------+
| aab | /tmp/submissions/bd9e6198-e57a-4dd0-b3ae-09f71efe1d44/application_d4bf0416_d5e1_4601_bb41_6096705da1e2.aab |
| track | internal |
| json_key | /tmp/submissions/bd9e6198-e57a-4dd0-b3ae-09f71efe1d44/service-account.json |
| package_name | com.ym2000.hoy |
| changes_not_sent_for_review | false |
| release_status | draft |
| skip_upload_apk | false |
| skip_upload_aab | false |
| skip_upload_metadata | false |
| skip_upload_changelogs | false |
| skip_upload_images | false |
| skip_upload_screenshots | false |
| sync_image_upload | false |
| track_promote_release_status | completed |
| validate_only | false |
| check_superseded_tracks | false |
| timeout | 300 |
| deactivate_on_promote | true |
| rescue_changes_not_sent_for_review | true |
| ack_bundle_installation_warning | false |
+------------------------------------+------------------------------------------------------------------------------------------------------------+
Preparing aab at path '/tmp/submissions/bd9e6198-e57a-4dd0-b3ae-09f71efe1d44/application_d4bf0416_d5e1_4601_bb41_6096705da1e2.aab' for upload...
Google Api Error: Invalid request - The Android App Bundle was signed with the wrong key. Found: SHA1: 5E:8F:16:06:2E:A3:CD:2C:4A:0D:54:78:76:BA:A6:F3:8C:AB:F6:25, expected: SHA1: B7:FB:5A:B6:F3:CE:5F:48:78:FF:8D:77:C0:41:06:05:8D:90:93:F0. - Retrying...
Google Api Error: Invalid request - The Android App Bundle was signed with the wrong key. Found: SHA1: 5E:8F:16:06:2E:A3:CD:2C:4A:0D:54:78:76:BA:A6:F3:8C:AB:F6:25, expected: SHA1: B7:FB:5A:B6:F3:CE:5F:48:78:FF:8D:77:C0:41:06:05:8D:90:93:F0. - Retrying...
Google Api Error: Invalid request - The Android App Bundle was signed with the wrong key. Found: SHA1: 5E:8F:16:06:2E:A3:CD:2C:4A:0D:54:78:76:BA:A6:F3:8C:AB:F6:25, expected: SHA1: B7:FB:5A:B6:F3:CE:5F:48:78:FF:8D:77:C0:41:06:05:8D:90:93:F0. - Retrying...
Google Api Error: Invalid request - The Android App Bundle was signed with the wrong key. Found: SHA1: 5E:8F:16:06:2E:A3:CD:2C:4A:0D:54:78:76:BA:A6:F3:8C:AB:F6:25, expected: SHA1: B7:FB:5A:B6:F3:CE:5F:48:78:FF:8D:77:C0:41:06:05:8D:90:93:F0. - Retrying...
Google Api Error: Invalid request - The Android App Bundle was signed with the wrong key. Found: SHA1: 5E:8F:16:06:2E:A3:CD:2C:4A:0D:54:78:76:BA:A6:F3:8C:AB:F6:25, expected: SHA1: B7:FB:5A:B6:F3:CE:5F:48:78:FF:8D:77:C0:41:06:05:8D:90:93:F0. - Retrying...
[!] Google Api Error: Invalid request - The Android App Bundle was signed with the wrong key. Found: SHA1: 5E:8F:16:06:2E:A3:CD:2C:4A:0D:54:78:76:BA:A6:F3:8C:AB:F6:25, expected: SHA1: B7:FB:5A:B6:F3:CE:5F:48:78:FF:8D:77:C0:41:06:05:8D:90:93:F0.
Fastlane supply failed
Failed to submit the app to the store
```
I downloaded the .aab file to check the SHA1 fingerprint:
```
$ keytool -printcert -jarfile application-8e8db738-c8a4-46b4-bc0f-4edb4518fdaf.aab
Certificate #1:
Owner: CN=Android Debug, OU=Android, O=Unknown, L=Unknown, ST=Unknown, C=US
Issuer: CN=Android Debug, OU=Android, O=Unknown, L=Unknown, ST=Unknown, C=US
Serial number: 232eae62
Valid from: Tue Dec 31 22:35:04 GMT 2013 until: Tue Apr 30 23:35:04 BST 2052
Certificate fingerprints:
SHA1: 5E:8F:16:06:2E:A3:CD:2C:4A:0D:54:78:76:BA:A6:F3:8C:AB:F6:25
SHA256: FA:C6:17:45:DC:09:03:78:6F:B9:ED:E6:2A:96:2B:39:9F:73:48:F0:BB:6F:89:9B:83:32:66:75:91:03:3B:9C
Signature algorithm name: SHA1withRSA (weak)
```
### Reproducible demo or steps to reproduce from a blank project
1. **Create/Configure EAS project with Android keystore:**
```bash
eas init
eas credentials --platform android
# Upload/generate keystore (we've tried multiple keystores)
```
2. **Configure build profiles in eas.json:**
```json
{
"build": {
"production": {
"android": {
"buildType": "app-bundle"
}
},
"beta": {
"extends": "production",
"android": {
"buildType": "app-bundle",
"distribution": "store"
}
}
}
}
```
3. **Run EAS build:**
```bash
eas build --platform android --profile beta
```
4. **Observe build logs showing correct keystore:**
```
✔ Using remote Android credentials (Expo server)
✔ Using Keystore from configuration: y-m2000 (default)
```
5. **Download and verify .aab signature:**
```bash
keytool -printcert -jarfile downloaded-app.aab
# Result: Shows debug keystore instead of expected production keystore
```
**Detailed Investigation Results:**
**Multiple Keystores Tested:**
- Original keystore "hoy-android-prod"
- Completely fresh EAS-generated keystore
- Manually uploaded keystore "y-m2000"
- All produce the same issue - builds are signed with the same debug keystore (SHA1: 5E:8F:16:06:2E:A3:CD:2C)
**Build Configuration Investigation:**
- EAS-generated `android/app/build.gradle` initially had `signingConfig signingConfigs.debug` in release builds
- This caused EAS to use debug keystore despite reporting correct production keystore in logs
- The problematic debug keystore SHA1 (5E:8F:16:06:2E:A3:CD:2C) is not found in:
- Local ~/.android/debug.keystore (which has different SHA1: 3F:1D:5F:61:47:CA:12:F1:C1:E9:BA:81:1E:C5:EA:AC:F4:DE:6A:3C)
- Any local keystore files in the project
- Any identifiable location in the development environment
**Environment Variable Setup:**
- `GOOGLE_SERVICES_JSON` properly configured in EAS environment
- Google services file creation works correctly in builds
- Only keystore injection issue persists
**Credential Verification:**
- `eas credentials` shows keystore exists and is accessible
- `eas project:info` shows correct project association (@y-m2000/hoy)
- No project ID or account ownership issues
- Credentials appear valid in EAS dashboard
- Multiple keystores tested all show correct details in EAS but wrong signature in final build
**Attempted Solutions:**
1. **Credential Management:**
- `eas credentials --clear` and regenerate keystore multiple times
- Multiple keystore uploads with different names
- Fresh project initialisation with `eas init --force`
- All attempts result in same debug keystore SHA1
2. **Build Configuration:**
- Analysed EAS prebuild process and gradle configuration
- Identified that `android/app/build.gradle` was hardcoded to use debug signing for release builds
- This explains why EAS reports correct keystore but actual build uses debug keystore
3. **Environment Debugging:**
- Verified project association and account ownership
- Checked for conflicting configurations
- Tested with EAS workflows vs direct builds
- Confirmed no local debug keystore matches the problematic SHA1
**Key Observations:**
1. **Credential Resolution Works:** EAS correctly identifies and reports using the configured keystore in build logs
2. **Gradle Override Issue:** EAS prebuild generates `android/app/build.gradle` with hardcoded debug signing configuration for release builds:
```gradle
release {
signingConfig signingConfigs.debug // This overrides EAS keystore injection
}
```
3. **Mysterious Debug Keystore:** The debug keystore used (SHA1: 5E:8F:16:06:2E:A3:CD:2C) is not found in:
- Local development environment
- Standard Android debug keystore locations
- Any identifiable source in the project or system
4. **Consistency Across Configurations:** Issue persists across:
- Multiple keystore configurations
- Different build profiles
- Various EAS credential setups
- Fresh project initialisations
5. **Platform-Specific:** Issue only affects Android builds; iOS builds work correctly
**Root Cause Analysis:**
The issue appears to be that EAS prebuild generates Android gradle configuration that hardcodes debug signing for release builds, overriding the EAS keystore injection mechanism. The generated `android/app/build.gradle` contains:
```gradle
buildTypes {
release {
signingConfig signingConfigs.debug // This is the problem
}
}
```
This causes the build system to ignore EAS credential injection and use a debug keystore instead. The specific debug keystore (SHA1: 5E:8F:16:06:2E:A3:CD:2C) appears to be either cached in EAS infrastructure or generated deterministically, but is not accessible or identifiable in the local development environment.
**Expected Behaviour:**
EAS Build should generate gradle configuration that allows EAS keystore injection, or the prebuild process should not hardcode debug signing for release builds when production keystores are configured.
**Actual Behaviour:**
EAS Build reports using the correct keystore, but the generated gradle configuration overrides this with debug signing, causing builds to be signed with an unknown debug keystore instead of the configured production keystore.
Contributor guide
Assessment
This issue has not been assessed yet.