store-shots

Troubleshooting

What the messages mean and how to fix them.

validate / generate

MessageMeaning / fix
No store-shots.config.json foundRun from inside an app, pass --project <app-dir>, or store-shots init --project <app-dir>
content.missing-localeCreate store/content/<locale>.json ({"locale":"de-DE","screens":{}}) or remove the locale from config.locales
content.missing-field / content.missing-screenCopy is missing for that locale/screen; strict mode blocks the job. Edit in the UI or the JSON
content.unused-field (warning)The screen's template does not show that field (an eyebrow under Full Bleed Card). The copy is kept for switching back; delete it if you do not need it
content.unknown-fieldNo template knows that field name: a typo, or a slide field (headline2) on a screen with one slide
content.starter-copy (warning)A theme's prompt ("What does this screen let you do?") is still the copy. Write the screen's own; readiness fails until every prompt is gone
content.glyph-missingA character is not covered by any local font. store-shots fonts add "<family>" (the message suggests one) and list it in brand.font.fallbacks
font.missingbrand.font.family (or headlineFont) is not downloaded: store-shots fonts add "<family>" --project <app>
source.missingRaw capture not found at store/raw/<device>/<locale>/<file>; capture it (store-shots capture --screen <id> --device iphone --locale <l>) or fix source.filePattern
source.aspect (warning)Capture aspect ratio differs from the target; the shell uses object-fit: cover, so it still renders, but use the right simulator (6.9" iPhone Pro Max, 13" iPad Pro) for fidelity
render.overflow ... even at the minimum allowed sizeCopy is too long for the box at the template's minimum font scale; shorten it or widen textWidth
render.text-overlaps-device (warning)Text box intersects the device. Intentional designs can ignore it; set validation.failOnTextOverlap to make it an error
content.store-claims (warning)Screenshot copy shows a price, discount, URL, ©, another platform or an Apple recognition, which Apple's asset guidelines rule out. Reword it
plan.too-few / plan.too-manyScreens per target/locale outside validation.screensPerTarget (Apple: 1–10)
manifest.override-invalidAn override key/value is outside the template's schema; see the allowed list in the hint
React is not definedThe CLI was run with a tsconfig other than the tool's. Use bin/store-shots.mjs / npx store-shots, which pin it
Playwright: Executable doesn't existnpx playwright install chromium inside tools/store-shots

Readiness

  • Metadata present for every locale fails → Listing edits fastlane/metadata/<locale>/*.txt; Start from the default language fills a new one.
  • Screenshots complete fails → generate; the check wants exact target dimensions and no alpha. Hand-made files that match a target count too; files of other sizes are listed as "matches no configured target" (warning).
  • App icon ... has an alpha channel is a warning: Expo prebuild flattens the iOS icon.
  • Screenshot sets cover the sizes Apple requires warns without a 6.1" iPhone set: Apple names it required, but scales a 6.9" set down when it is missing. Add iphone-6.1-1206x2622 to the targets; it renders from the same captures. It fails when ios.supportsTablet is true and there is no iPad 13" set.
  • Keywords follow Apple's guidance fails over 100 bytes (Japanese, Chinese, Arabic and Cyrillic take 2-3 bytes per character) and warns on plurals of included words, category names, "app", repeated words, #/@ and terms of two characters or fewer.

Fastlane runner

  • Upload lanes are disabled while readiness fails; enter an override reason to force them (logged).
  • lane "<name>" not found in fastlane/Fastfile → the app's Fastfile lacks the lane; add it (see Uploading with fastlane) or point fastlane.lanes at the lane it has.
  • Output is the real fastlane output; credentials and ASC behaviour are fastlane's, not the tool's.
  • fastlane is found at /opt/homebrew/bin/fastlane, /usr/local/bin/fastlane, $STORE_SHOTS_FASTLANE, or on PATH.

Capture

  • No booted simulator → boot one in Simulator.app. store-shots capture --list shows what is booted.
  • already exists; pass --force → captures are never overwritten silently.
  • Non-localized screens (source.localized: false) only accept the default locale.
  • Clean status bar: --clean-status-bar (9:41, full battery/signal). Other locales: the command prints the simctl commands to switch the simulator language.

Determinism

Outputs are byte-identical for identical inputs (fonts bundled/locally downloaded, fixed viewport, animations disabled, Sharp flatten). If a second generate re-renders everything, something in inputsSha256 changed: the capture, copy, overrides, brand, output settings, fonts or the tool version. --force re-renders regardless.

On this page