storebound/skills/store-pitfalls/SKILL.md

5.4 KiB

name description
store-pitfalls Known pitfalls with App Store Connect, Google Play and storebound itself, learned from real releases, and what to do about each - store lists that lag right after a create, dry runs that print a count instead of a plan, App Store names taken on a storefront, keyword limits in bytes, Data safety answers without code evidence, missing font glyphs in screenshots, console sign-in and sessions, Capacitor monorepo plugins. Read it before any store task, and when a store command does something you did not expect.

Store pitfalls

Each entry: symptom → cause → what to do → what guards it now. The full changelog of lessons with dates is docs/pitfalls.md in the storebound repository. When you hit a new one, tell the owner and add it there (and here).

1. A product you just created is "not there"

  • Symptom: apple iap-review uploads nothing for a product apple iap created a minute ago; a list looks short.
  • Cause: App Store Connect's /inAppPurchasesV2 list (and Play's product list) can lag for a short while after a create. A command that walks the list skips what is not in it yet.
  • Do: wait a minute and re-run. Never assume a product was handled because the command finished.
  • Guard: apple iap-review compares the config's products with the store's list, names the missing ones ("the store's list can lag a minute after creating; re-run") and exits 1. apple iap and play products read the list again after creating and warn about any new product that is not in it yet; their dry runs name products that are not on the store.

2. A dry run that only prints a count

  • Symptom: --dry says "listing: 20 locales" or "3 change(s)", but not which fields would change to what.
  • Cause: the command logged a summary instead of the plan.
  • Do: never ask the owner to approve a count. Show the rows that change (item, action, old → new). If a command only prints a count, say so and show the owner the diff from pull / --json output instead.
  • Guard: cli/lib/dry.ts dryPlan(title, rows) prints the standard plan table (apple iap, apple iap-review, play products use it); tests/pitfalls.test.ts scans cli/** for --dry branches that print nothing but a count.

3. "The app name you entered is already being used"

  • Symptom: creating the App Store record or saving the name fails although you own no app with that name.
  • Cause: App Store app names are unique per storefront, across all developers.
  • Do: ask the owner for a variant (a short suffix such as "Example Notes: Lists") and set apple.name in the config; keep app.name for Play and the brand. Do not pick the suffix yourself.
  • Guard: apple.name overrides the App Store name.

4. Keyword field "too long" at fewer than 100 characters

  • Symptom: App Store Connect rejects keywords that look short enough, mostly in Turkish, German, CJK.
  • Cause: the 100 limit counts UTF-8 bytes, not characters ("ş" is 2 bytes, a CJK character 3).
  • Do: shorten by bytes; drop words, not commas.
  • Guard: storebound check counts bytes for keywords.

5. Data safety says "email collected" for an app that never asks for one

  • Symptom: the proposal marks email (or phone) as collected because the app has accounts.
  • Cause: account features do not imply email collection (anonymous ids, Game Center, Play Games sign-in).
  • Do: answer only what the code proves; ask the owner for the rest (rule 5).
  • Guard: storebound scan marks email only with evidence (an email field, an email sign-up call) and otherwise says "ask owner".

6. Boxes or wrong glyphs in localized screenshots

  • Symptom: Turkish, Polish or Vietnamese captions show fallback glyphs (ş, ğ, ł, ệ) while the English ones are fine.
  • Cause: the font (or the Google Fonts subset that was downloaded) does not cover those characters, and the browser silently draws them with another font.
  • Do: check every language's characters before rendering, pick a font that covers them or let the fallback fill in.
  • Guard: storebound shots fonts / shots check check each language's characters against the fonts' glyphs.

7. Console automation stops at sign-in or loses the session

  • Symptom: console fill waits on a sign-in page, cannot find fields, or is signed out on the next run.
  • Cause: the App Store Connect sign-in runs inside an idmsa.apple.com iframe; "User Access" is a plain heading, not a labeled group; Chrome drops session cookies unless the last session is restored.
  • Do: let the owner sign in in the opened window (never type credentials); re-run after the sign-in.
  • Guard: the console session handles the iframe and the plain heading and starts Chrome with --restore-last-session; a partial miss fills every field found and leaves only the missing ones to the owner.

8. scan misses Capacitor plugins in a monorepo

  • Symptom: SDKs or privacy manifests of Capacitor plugins are not found.
  • Cause: the plugins live in apps/native/node_modules (a workspace package), not in the root node_modules.
  • Do: run scan from the project root; check that the stack line lists the plugins.
  • Guard: storebound scan and privacy-manifest resolve packages through workspace folders too.

Adding a lesson

Every bug found in real use gets an entry in docs/pitfalls.md and here, and, where possible, a check or a test that fails without the fix (see CONTRIBUTING.md).