Build number is present and incremented for each release
Why it matters
Both Apple and Google reject any binary whose build identifier is missing, non-integer, or less-than-or-equal to a previously shipped build for the same version string — the upload fails with ITMS-90062 on iOS or a duplicate-versionCode error on Play Console, blocking the release outright. Without a monotonically incrementing build number, TestFlight cannot route the correct artifact to internal testers, Play Console staged rollouts lose their ordering, and crash reports merge across builds so regressions become untraceable. This is an operational tripwire that delays launches by hours every time it fires.
Severity rationale
Low at the code level because fixes are mechanical, but each missed increment costs a full submission round-trip.
Remediation
Declare ios.buildNumber as a string and android.versionCode as an integer in app.json, then automate monotonic increments in CI so human error never ships a duplicate. Store the last-shipped build in a lockfile or release-notes table and fail the build if the new value does not exceed it.
// app.json
{
"expo": {
"version": "1.0.3",
"ios": { "buildNumber": "42" },
"android": { "versionCode": 42 }
}
}
Detection
- ID:
build-number-incremented - Severity:
low - What to look for: Check
app.jsonforbuildNumber(orios.buildNumber,android.versionCode). Count all build number declarations found across config files. The build number should be an integer that increments with each build or release. Verify it is higher than the previous release (if known). For Android,versionCodemust be an integer; for iOS,buildNumbercan be any string but integers are standard. - Pass criteria: Build number exists and is a positive integer (at least 1). If there is a history of releases, current build number is higher than previous (indicating new build). Both iOS
buildNumberand AndroidversionCodemust be consistent. - Fail criteria: Build number is missing, is not a positive integer (e.g.,
1.0instead of1, or0), or is lower than a known previous build. - Skip (N/A) when: First release of the app (build number can start at
1). - Detail on fail:
"buildNumber is missing from app.json"or"buildNumber is '1' but previous release was '5' — should increment" - Remediation: Build numbers allow app stores to sequence releases. Implement:
- In app.json:
Or separately:"version": "1.0.3", "buildNumber": "1""ios": { "buildNumber": "1" }, "android": { "versionCode": 1 } - Increment build number for each build (even if version number stays the same):
- Version:
1.0.0, Build:1(first release) - Version:
1.0.0, Build:2(second build of 1.0.0, e.g., if first was rejected) - Version:
1.1.0, Build:3(new feature release)
- Version:
- For CI/CD, automate incrementing:
# Increment build number ./increment-build.sh - Never decrement build numbers — stores reject lower build numbers
- In app.json:
Taxons
History
- 2026-04-18·v1.0.0·Initial import from mobile-store-readiness·automated