Testers on an old or broken build: how to move them to the fix
· 9 min read
Build 117 crashes on login for anyone with an older account. You fixed it in build 118 an hour later. The next morning, three testers are still on 117, one of them has filed the same crash twice, and a client has just scanned the QR code you sent last week and installed 117 for the first time.
Prompting testers from inside the app is one part of the answer, and we cover that in telling testers a new build is ready. This guide is about the other part: what you, the owner of the builds, can do on your side so the old build stops spreading and the people on it move to the fix. The steps work with any distribution tool that has the controls; the examples use AppForShare.
First, decide what kind of old build it is
Not every old build needs the same response.
- Outdated: it works, a newer one exists. You want testers to move, but nothing is on fire. A prompt is enough.
- Worse than the one before: the newest build has a regression. You want the link to go back to the previous build while you fix it.
- Broken: it crashes, cannot sign in, or does harm, such as writing bad data to a shared test server or sending real emails. You want nobody new to install it and everybody on it to stop using it.
The further down that list, the stronger the tool you reach for.
Step 1: give testers a link that never goes stale
Most testers on old builds are there because the link they have points at an old build. Every new upload makes a new link, and the old one keeps working. The fix is a link per audience that always opens the newest build in it.
On AppForShare that is a channel, on Pro and Team: Beta, Live, or one per client, each with a stable link and QR code. You put a build into a channel from the build page or from CI, and the channel link opens it from then on. iPhones get the iOS build and Android phones the Android build of the same channel. Send channel links, not build links, and the QR code printed on a sticky note last month still opens the fix.
Step 2: roll the channel back when the new build is worse
If 118 turns out worse than 117, put 117 back into the channel. The channel link opens 117 again for everyone who taps it, and the update check (Step 5) reports 117 as the newest build. Two things a rollback does not do: it does not change apps already installed, and on Android a tester on 118 needs to uninstall before installing 117, because Android will not install a lower versionCode over a higher one. Say that in your message, since an uninstall clears the app's local data.
Step 3: stop new installs of the old build
The build link of 117 still works for anyone who has it: an old email, a ticket, a QR code in a slide deck. On Pro and Team, install link controls close it without deleting it:
- Pause: the install page shows a short message from the owner instead of the Install button, and the download is refused. Resume any time.
- Stop date: the link takes no installs after the end of that day (UTC). Good for builds you know will be outdated after a demo.
- Install limit: a cap on installs for that build, useful for a build meant for a fixed group.
Installed apps keep working; these controls only stop new installs. That is often enough for an outdated build. For a broken one, use Step 4.
Step 4: retire the broken build
Retiring is the strongest step, and it is built for the build 117 case. On Pro and Team, the owner marks a build as retired from the build page, with an optional note such as "Crashes on login. Install the newer build." From then on:
- The build's link takes no installs.
- Its install page shows your note and a button to the newest build of the same app and platform that is not retired, so a tester who opens an old link is one tap from the fix.
- Channels skip it. If the retired build was the newest in a channel, the channel link falls back to the build before it.
- The in-app update check answers
retired: truewhen the app asks about that build number, and givesminBuild, one above the highest retired numeric build number of that app and platform.
You can bring a retired build back on any plan, if you retired the wrong one. From the CLI:
# Put the fix into the channel testers use
appforshare promote 4821 --channel beta
# Retire the broken build, with a note testers will see
appforshare retire 4817 --reason "Crashes on login. Install the newer build."
# Changed your mind
appforshare retire 4817 --undo
More on the retire a test build page. Retiring does not delete anything, so the build's feedback, installs and "what changed" history stay where they were.
Step 5: let the build itself refuse to go on
Steps 1 to 4 fix the links. They do nothing for the tester who installed 117 yesterday and opens the app from the home screen today. Only code inside the build can reach that person.
On Pro and Team, each channel has a public JSON address the test build can read, described in the update check docs. Add &build= with the app's own build number and the answer says whether that build is retired, with your note, plus minBuild. A minimal check looks like this (the snippets in the docs cover Swift, Kotlin, Flutter and React Native):
// Test builds only. Ask the channel about this exact build number.
val url = "https://appforshare.io/api/c/YOUR_CHANNEL/latest" +
"?platform=android&build=${BuildConfig.VERSION_CODE}"
val latest = fetchLatest(url) ?: return // no network: do nothing
val min = latest.minBuild?.toLongOrNull()
val mustUpdate = latest.retired == true ||
(min != null && BuildConfig.VERSION_CODE < min)
if (mustUpdate) showBlockingUpdate(latest.installUrl, latest.retiredReason)
else if ((latest.build?.toLongOrNull() ?: 0) > BuildConfig.VERSION_CODE) showUpdateBanner(latest.installUrl)
Two levels, on purpose. A retired or too old build gets a screen it cannot dismiss, with the note and an Install button. A build that is only behind gets a banner the tester can close. Never block on a network error: if the check fails, let the app run.
This check belongs in test builds only, compiled in through a build configuration or flavor. Apple's guideline 2.5.2 and Google Play's self update rules are the reasons, as the prompt article explains.
Step 6: tell the people, once
A short message helps the testers who do not open the app every day. Keep it to three lines: which build is broken, what to do, the channel link. On AppForShare, Pro and Team can email the install link to up to 5 addresses per build. On Team, testers on a tester list get an email for new builds, the per tester status shows who is "on an older build", and a reminder goes to the ones who have not moved. Slack, Microsoft Teams, Discord and Google Chat webhooks post each new build to your team channel.
If the broken build touches a shared server
When a build does harm, such as writing bad records to a staging database, the app side is not enough, because a tester may never update. If your test builds send their build number in a header, your test server can refuse requests from that build number with a clear message. This is your backend, not your distribution tool, but it is the only control that works even when the tester ignores every prompt.
Store apps are a different problem
Everything above is for test builds installed from a link. Apps installed from the App Store or Google Play update through the store, and the tools are different. Google Play has the in-app updates API with flexible and immediate flows. On iOS, apps compare their version with the store version and send users to the App Store. Vendor SDKs package this: AppsOnAir (by Logicwind) sells AppSync, an SDK that checks at launch for a force update, an optional update or maintenance mode set in its portal, while the update itself still comes from the store; as published in November 2026 it is on its paid plans. Do not reuse your test build check for this: a store build must never point users to an ad hoc install page.
Mistakes that keep testers on old builds
- Deleting the old build. Testers who open its link see that it is gone, with no way to the fix. Retiring keeps the page and points it at the newer build.
- The same build number twice. If 117 and the fix are both called 117, no check can tell them apart. Raise the build number on every build you hand out.
- A fix outside the channel. Uploading the fix without putting it into the channel leaves the channel link on the broken build.
- A new link per message. Every new address is one more place an old build can live. Send the channel link every time.
A quick playbook
| Situation | What to do | Plan on AppForShare |
|---|---|---|
| A newer build is out, the old one is fine | Promote it into the channel; let the update check prompt | Pro and Team |
| The new build is worse than the last one | Point the channel back at the older build | Pro and Team |
| Nobody new should install an old build | Pause it or set a stop date | Pro and Team |
| The build is broken and testers must leave it | Retire it with a note; the update check blocks it | Pro and Team |
| The build writes bad data to a shared server | Retire it and refuse its build number on your server | Your backend |
| Testers need to hear about it | Email the link, tester emails, chat webhooks | Pro and Team; tester lists on Team |
Common questions
Can I force testers to update a test build?
Only from inside the app. Retire the old build and have the test build check retired and minBuild at launch, then show a screen that cannot be dismissed. Links alone stop new installs, not existing ones.
Does retiring or pausing a build remove it from phones?
No. Nothing can remove an installed app remotely through an install link. The tester keeps the app; your controls decide what the link and the update check say.
What happens to a channel when its newest build is retired?
The channel skips it and opens the build before it, until you put a newer build in.


