A rejection post-mortem template: six steps from letter to fix without guessing
Most rejections are lost to guessing, not to Apple. The letter arrives, you read it once, you form a theory in about ninety seconds, you change three things that felt related, and you resubmit. Then it comes back, and you have learned nothing, because the experiment had three variables and no control.
The fix is a process boring enough to follow when you are annoyed. Six phases: read the citation, reproduce, isolate, fix, document, reply. It takes longer than guessing on the first rejection and much less time by the second.
1. Read the citation
There are three separate things in a rejection message and they carry different weight.
The guideline number. This is an index, not an explanation. Look it up and read the actual paragraph on Apple's guidelines page rather than your memory of what that number means. Numbers get restructured, and the template in the letter often lags the published text.
The template paragraph. Boilerplate that App Review sends to everyone who trips that rule. It tells you the category of problem. It tells you nothing about your app, so do not read intent into its wording.
The reviewer's own sentences. This is the only part written about your app, and it is the part people skim. It is where the device, the OS version, the screen name, the button they tapped and the account they used will appear, if they appear anywhere. Copy these sentences out verbatim before you do anything else.
Then establish one more thing: is this a binary rejection or a metadata rejection? A metadata problem is fixed in App Store Connect and needs no new build. A binary problem needs a new build and a new upload. Getting this wrong wastes a full cycle, and people get it wrong constantly because both arrive as the same kind of message.
2. Reproduce
Reproduce it before you theorise about it. Specifically:
- On the OS version the reviewer named, or the current release if they named none
- On the device class they named, and if none, on the smallest screen in your screenshot set
- On a clean install, with no state left over from your own testing
- On the exact build you submitted, from the archive, not on your working branch
That last one matters more than it sounds. The bug may already be gone on main, which means you would ship a fix for something else entirely and never know why the resubmission passed.
If you cannot reproduce it, that is a finding, not a failure. Write down "reproduced: no" and what you tried. Reviewers test on networks you cannot replicate, behind logins that failed, on hardware you do not have, in regions with different content. A reviewer who could not get past your sign-in screen has given you real information about your sign-in screen, and it is your problem to fix even though it works for you.
An honest reply that says "we could not reproduce this on iOS 26 on iPhone 15, here is what we tried, could you tell us which screen" is a normal thing to send, and it works better than a confident fix for the wrong thing.
3. Isolate
One variable.
Write down the smallest change you believe will clear the citation. Not the best change, not the change you have wanted to make for a month. The smallest one that addresses the thing you were actually cited for.
Then record it against a build number, so the resubmission is an experiment with one input and a readable result. If it passes, you know what fixed it. If it fails, you know that was not it, which is also worth having.
Resisting scope here is the entire skill. Every extra change you bundle in is a variable, and it is also new surface for review to find something else in.
4. Fix
Fix the cited thing before the tempting thing.
While you were reproducing you noticed four other problems. Write them down and ship them separately, after this is cleared. They are not free: they add review surface, they add regression risk, and they destroy your one-variable experiment.
If the fix is a product decision rather than a bug, say so out loud. "We are removing the feature" and "we are keeping the feature and arguing" are both legitimate, and they are different decisions with different costs. What is not legitimate is drifting into one of them by accident because it was the path of least resistance at 11pm.
5. Document
Write the entry now, while you still remember which build and which screen.
This is the step everyone skips and the only one that compounds. The same guideline hits the same team repeatedly, because the same guideline describes the same class of mistake and you have not changed how you work. A written record turns the second occurrence from a two-day investigation into ten minutes of reading.
It also survives you. The person who handles the next rejection may not be the person reading this.
6. Reply
Short, factual, specific. Three things: what you changed, where to find it, and how to verify it.
Thank you for the review.
The account deletion option cited in the rejection is now available in Settings > Account > Delete Account, reachable in two taps from the home screen. It deletes the account server-side rather than only signing out.
This is in build 47, uploaded today. The demo account in App Review Information has been reset and verified this morning.
If anything above does not match what you saw, please let us know which screen and we will address it directly.
Do not argue the guideline unless you genuinely believe the reviewer had the wrong app or the wrong build. Arguing first costs you a cycle and reads as a developer who has not looked. Arguing second, with a reproduction attempt behind you, is credible.
The template
Copy this into whatever your team already reads. A file in the repo, a page in your notes, an issue template. Somewhere that is not one person's memory.
## Rejection post-mortem
Date: [when the rejection arrived]
App and version: [app name, version string]
Build number: [the build that was rejected]
Submission type: [binary or metadata]
Guideline cited: [number and section name from the letter]
Template paragraph: [paste the boilerplate verbatim]
Reviewer's own words: [paste only their sentences, verbatim]
Device and OS named: [what they said they tested on, or "none given"]
Reproduced: [yes / no / partially]
Reproduction notes: [what you tried, on what device and OS, on which build]
Root cause (one line): [the actual cause, in one sentence]
Smallest fix identified: [the minimum change that addresses the citation]
What changed: [the change, and the build number it shipped in]
What deliberately did not change:
[everything you noticed and chose not to bundle in]
Reply sent: [date, and paste the reply]
Outcome: [approved / rejected again / still waiting] on [date]
Next time: [what we change in how we work, not in the app]
The last field is the one that pays for the rest. "Next time: add the smallest screen size to the pre-submission device list" is worth more than any of the fields above it.
The traps
- Changing several things at once. You will not know what fixed it, and you will do it again.
- Replying before reproducing. You are guessing in writing, on the record.
- Arguing the guideline first. It costs a cycle and it costs credibility.
- Resubmitting the same build. Happens more than anyone admits, usually when the fix was in App Store Connect and the build was never re-uploaded, or when the archive was rebuilt without the change.
- Letting the record live in one person's head. Then the second occurrence costs full price.
When to stop iterating and escalate
Iterating is right when the citation describes something in your app. Escalating is right when you believe the decision is wrong rather than the app: the reviewer tested a different app, the cited behaviour does not exist in your build, or the same submission has been rejected twice for reasons that contradict each other.
For those, the App Review Board is the route, and it needs the thing this process produces anyway: a clear statement of what was cited, what you checked, what you found, and what you changed. Escalating without that is just a louder guess.
AppSubmit keeps the rejection, the guideline, the build number and the reply on the release itself, which is the same record as the template above, filled in as you go. The template works perfectly well in a text file.
Related
- Metadata Rejected vs Rejected (
metadata-rejected-vs-rejected) - Guideline 4.3(a), Design Spam (
apple-guideline-4-3-a-design-spam) - Guideline 2.3.1, Hidden Features (
apple-guideline-2-3-1-hidden-features) - What In Review actually means (
in-review-status-meaning)