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

  1. Keep released version components below 100 (bump major earlier, e.g. 0.99.x => 1.0.0).
  2. Use small numeric prerelease identifiers (beta.1, beta.2, ...) instead of large ones.
  3. If a component must exceed 99, change the packing scheme/RADIX in getMobileBuild and re-derive build numbers consistently for both stores.
  4. 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

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)