Guideline 2.3.1: hidden or undocumented features
A Guideline 2.3.1 rejection means the reviewer believes your app can do something they were not shown. Sometimes that is a debug menu you forgot to strip. Sometimes it is a feature flag they suspect is hiding behaviour behind a server switch.
Treat this one seriously. Most rejections cost you a resubmission. This is the family where Apple talks about removing apps and terminating accounts, so the reply matters as much as the fix.
How it is usually worded
The header arrives as Guideline 2.3.1 - Performance - Accurate Metadata, and the body tends to be one of:
- "We discovered that your app contains hidden features."
- "Your app includes functionality that was not disclosed in your submission."
If the message names nothing, ask; the range of possible causes here is wide.
What it actually means
The guideline asks you not to include hidden or undocumented features, and to describe new features, functionality and product changes with specificity in the Notes for Review. It also says that "bug fixes" alone is not an acceptable description of an update.
Read it as a rule about disclosure rather than about secrets. Apple is not objecting to feature flags as an engineering practice. It is objecting to a review that cannot see what the app actually does, because everything the reviewer approves is a snapshot of code whose behaviour you can change afterwards.
That is also why the consequences escalate. A layout bug is a mistake. Shipping behaviour that only turns on after approval looks deliberate.
Why it triggers
- A debug or QA menu still reachable. Long-press on the version label, a five-tap gesture on the logo, a hidden row in Settings. Reviewers do tap around, and a menu full of environment switches reads exactly as a hidden feature.
- Test accounts that see more than production. You gave the reviewer credentials tied to an internal role, so they saw admin screens, unreleased tabs, or a staging environment. Now the app they reviewed is not the app you shipped.
- Remote config that gates whole features. A flag service that can enable a screen, a payment path or a content type after approval. This is the hardest one to answer, because it is true.
- Dormant code paths with visible edges. A locked tile with a "soon" badge, a settings toggle for a feature that is not in the build, localisation strings for a screen that does not exist.
- Review notes that say nothing. "Bug fixes and performance improvements" for a release that added a social feed. The guideline names this directly.
How to fix it, in order
- Ask what they found, if they did not say. One line in Resolution Center: "Could you confirm which feature or screen was identified as undisclosed, so we can address it precisely?" Guessing across a whole codebase is worse than waiting.
- Strip the debug surface from release builds. Compile it out rather than hiding it.
#if DEBUGaround the entry point, not a boolean you can flip. Then install the App Store build from TestFlight and try to find it yourself. - Rebuild the review account as a normal user. Same role, same permissions, same content a real new signup gets. If the reviewer needs elevated access to see a feature, say so explicitly in Review Notes and explain why.
- Audit your flags and write them down. List every remote flag that can change what the user sees. For each one, decide: does it change features, or does it change rollout percentage and copy? The first kind needs disclosing. The second is ordinary.
- Set flags to their shipped state in the reviewed build. Whatever the reviewer sees should be what a store customer sees on day one. If a feature is off, ship it off and disclose that it exists.
- Remove the edges of unshipped features. No locked tiles, no "coming soon" rows, no strings for screens that are not there.
- Rewrite the Review Notes. Specific, per feature, in the order a reviewer meets them, with a demo path and working credentials.
- Never ship a change of purpose behind a flag. If the flag would turn a note-taking app into a marketplace, that is not a disclosure problem, it is the thing the guideline exists to stop.
What to send back
Be concrete about the mechanism, and volunteer the audit. Reviewers respond better to a developer who explains their flag system than to one who denies having one.
Thank you for the review. We have identified and removed the internal diagnostics menu that was reachable by long-pressing the version number on the About screen; it is now compiled out of release builds entirely and is not present in build 214. We have also replaced the review credentials with a standard customer account so the app behaves exactly as it does for a new user. Our Review Notes now list every feature in this release with the steps to reach each one.
If remote configuration is the real subject:
Thank you for the review. To be transparent about our configuration: the app uses a remote flag service, and we have audited every flag it can read. None of them add screens, payment paths or content types. They control the rollout percentage of the redesigned onboarding described in our Review Notes, and two pieces of marketing copy. Build 214 ships with every flag in the state a new customer receives, and the app cannot download or execute code. We are happy to provide the full flag list if that would help.
When it is really a different guideline
- Downloading executable code or a script payload is 2.5.2.
- A feature that is visibly broken or incomplete rather than hidden is 2.1 or 4.0.
- Metadata that overstates what the app does is elsewhere in 2.3.
- Repeated or deliberate concealment moves the conversation to 5.6, the Developer Code of Conduct, where the consequences are account level.
AppSubmit keeps release notes and reviewer instructions with each submission, so the list of what changed and how to reach it exists before you open App Store Connect. A file in the repo works fine too.
Source: Apple, App Store Review Guidelines, 2.3.1 (https://developer.apple.com/app-store/review/guidelines/#accurate-metadata)
Related: apple-guideline-2-5-2-executable-code, apple-guideline-5-6-developer-code-of-conduct, apple-guideline-2-2-beta-testing