immich-app/immich · error · Error
Cannot derive a mobile build number from
Error message
Cannot derive a mobile build number from ${version.format()} What it means
getMobileBuild derives a monotonic integer mobile build number from a semver as major*100^3 + minor*100^2 + patch*100 + digit. Each component must be < 100 and a prerelease digit must be < 99, otherwise the packed integer would be ambiguous; when those bounds fail, this Error is thrown with the formatted version.
Solutions
- Keep released version components below 100 (bump major earlier, e.g. 0.99.x => 1.0.0).
- Use small numeric prerelease identifiers (beta.1, beta.2, ...) instead of large ones.
- If a component must exceed 99, change the packing scheme/RADIX in getMobileBuild and re-derive build numbers consistently for both stores.
- Verify the version passed to getMobileBuild is the intended one; a malformed version can overflow a component.
Example fix
// before "version": "1.101.0" // patch/minor >= 100 => throws // after "version": "2.0.0" // components < 100, build = 2*1000000
Defensive patterns
Strategy: validation
Validate before calling
const isMobileSafe = (v: SemVer) =>
v.major < 100 && v.minor < 100 && v.patch < 100 &&
(v.prerelease.length === 0 || (v.prerelease[1] as number ?? 99) < 99);
if (!isMobileSafe(version)) failFast(`cannot pack ${v.format()} into a build number`); Try / catch
try {
const build = getMobileBuild(version);
} catch (e) {
if (String(e).startsWith('Cannot derive a mobile build number')) {
console.error('bump major (or shrink prerelease id) before releasing mobile');
process.exit(1);
}
throw e;
} Prevention
- Keep major/minor/patch below 100 in mobile release planning
- Use small numeric prerelease identifiers (beta.1..98)
- Validate the packed build number in CI before store submission
When it happens
Trigger: Releasing an app version where major, minor, or patch >= 100, or a prerelease whose second element (the numeric identifier, e.g. the .5 in 1.2.3-beta.5) is >= 99.
Common situations: Very mature packages reaching x.100.0 or y >= 100 patch, or prerelease tags with large numeric identifiers; usually in long-lived mobile release automation for Immich's iOS/Android builds.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15).
Data as JSON: /api/errors/57fd06397e95f2fa.
Report an issue: GitHub.
Appendix: source
Thrown at packages/scripts/src/commands/release.ts:203
return newVersionRaw;
};
const RADIX = 100;
const STABLE = RADIX - 1;
export const getMobileBuild = (version: SemVer) => {
const { major, minor, patch, prerelease } = version;
const candidate = prerelease[1];
const digit = typeof candidate === 'number' ? candidate : STABLE;
const valid =
major < RADIX &&
minor < RADIX &&
patch < RADIX &&
(prerelease.length === 0 || digit < STABLE);
if (!valid) {
throw new Error(
`Cannot derive a mobile build number from ${version.format()}`,
);
}
return (
major * Math.pow(RADIX, 3) +
minor * Math.pow(RADIX, 2) +
patch * RADIX +
digit
);
};
const pump = (path: string, pattern: RegExp, replacement: string) => {
const file = new TextFile(path);
const update = file.read().replace(pattern, replacement);
file.write(update);
};
View on GitHub (pinned to e55ac299a4)