What happens
The metadata refresher treats "not in the GB storefront" and "does not exist" as the same thing. Apple returns HTTP 200 with an empty result set in both cases, lib/appStore.js infers absence, and scripts/refresh-app-store-metadata.js records app_not_found.
Observed on the first real cron run:
Refresh failed for com.kfirapps.testi: app_not_found
But the app is live — just not in GB:
itunes.apple.com/lookup?bundleId=com.kfirapps.testi&country=gb → resultCount: 0
itunes.apple.com/lookup?bundleId=com.kfirapps.testi&country=us → resultCount: 1 (Testi Apps Limited)
GB is the storefront everywhere: APP_STORE_COUNTRY defaults to gb in the refresher, and routes/index.js:23 hardcodes const COUNTRY = 'gb' for lookups and queueing. So an app that was in the GB storefront when it was queued and later withdrawn from it becomes permanently unrefreshable.
Why it matters
fetched_at only advances on a successful fetch, so for these apps:
- "Store metadata checked" on the report page freezes at whatever the last success was — for pre-migration-013 rows, that is
apps.added, i.e. the queue date.
- The row sits in the capped exponential backoff being retried every 30 days, forever, and never succeeds.
- Nothing on the page distinguishes this from a refresher that is simply broken. This is the same visible symptom as the stale-date bug that turned out to be the cron never running, which made it harder to diagnose.
The displayed tracker analysis stays valid — this is only about metadata freshness and what the page tells the reader.
Options
- Leave it. The site is GB-scoped by design; an app absent from GB is arguably out of scope. Costs nothing, keeps the misleading date.
- Fall back to another storefront (e.g.
us) before recording app_not_found, so metadata keeps refreshing. Cheap, but mixes storefronts in one cache row — version and availability would no longer describe GB.
- Record storefront-absence distinctly from a refresh failure: its own state on the cache row, so the refresher can stop retrying it on the normal cadence and the report page can say something honest like "no longer available in the UK App Store". Most work, best outcome for readers.
Leaning towards 3, with 1 as an acceptable interim since nothing is actually broken.
Not this
Unrelated to #26 (pausing and resuming when Apple throttles) — that is about 403/429, a different path entirely.
What happens
The metadata refresher treats "not in the GB storefront" and "does not exist" as the same thing. Apple returns HTTP 200 with an empty result set in both cases,
lib/appStore.jsinfers absence, andscripts/refresh-app-store-metadata.jsrecordsapp_not_found.Observed on the first real cron run:
But the app is live — just not in GB:
GB is the storefront everywhere:
APP_STORE_COUNTRYdefaults togbin the refresher, androutes/index.js:23hardcodesconst COUNTRY = 'gb'for lookups and queueing. So an app that was in the GB storefront when it was queued and later withdrawn from it becomes permanently unrefreshable.Why it matters
fetched_atonly advances on a successful fetch, so for these apps:apps.added, i.e. the queue date.The displayed tracker analysis stays valid — this is only about metadata freshness and what the page tells the reader.
Options
us) before recordingapp_not_found, so metadata keeps refreshing. Cheap, but mixes storefronts in one cache row — version and availability would no longer describe GB.Leaning towards 3, with 1 as an acceptable interim since nothing is actually broken.
Not this
Unrelated to #26 (pausing and resuming when Apple throttles) — that is about 403/429, a different path entirely.