Collected from support email and our own deployments. Each entry gives the symptom you see, the cause, and the fix. The first tool to open for any of them is Chrome DevTools → Application, which reports manifest parsing, installability failures and service worker state in plain text.
Installation never offered
1. The site is not fully on HTTPS
Symptom: no prompt; DevTools says "Page is not served from a secure origin". Cause: the page loads over HTTP, or HTTPS redirects to HTTP somewhere. Fix: force HTTPS site-wide and check the redirect chain with curl or a header checker.
2. The manifest returns HTML
Symptom: "Manifest could not be parsed". Cause: /manifest.json is being caught by a CMS route or a 404 page returning 200. Fix: open the URL directly — you should see raw JSON — and add a rewrite exception if you don't.
3. Wrong or missing icon sizes
Symptom: "Manifest does not contain a suitable icon". Cause: no 192×192 or no 512×512, or the sizes attribute doesn't match the actual pixels, or the file is SVG only. Fix: export real PNGs at both sizes with the icon resizer and make sizes exact.
4. display is browser or missing
Symptom: installable check fails on display mode. Fix: set "display": "standalone".
5. start_url outside scope, or on another origin
Symptom: "start_url is not in scope" or manifest rejected. Fix: make both relative to the same origin; scope must be a prefix of start_url.
6. Expecting a prompt on iPhone
There isn't one. See the iOS guide and write install instructions.
Installed but looks wrong
7. Blurry or screenshot icon on iOS
Cause: no <link rel="apple-touch-icon">. Safari ignores manifest icons. Fix: add a 180×180 PNG link in the head.
8. Logo clipped inside a circle on Android
Cause: an unpadded icon marked purpose: "maskable", or no maskable icon so Android shrinks the "any" icon into a white circle. Fix: provide a padded maskable variant (safe zone = central 80% circle) and keep the plain one as any.
9. A browser bar appears inside the app
Cause A: the user navigated outside scope — typically a link to www. when the app is on the bare domain, or to a subdomain. Fix: canonicalise links to one host; widen scope only if those pages belong in the app. Cause B (TWA): assetlinks.json failed verification. Fix: fingerprint from Play's app-signing key, file served without redirect.
10. Wrong colour behind the status bar
Cause: a page-level <meta name="theme-color"> overriding the manifest with an old value. Fix: align them, or use media-query variants for light/dark deliberately.
Installed but misbehaves
11. Stale content forever
Cause: HTML cached with cache-first, or the cache name never bumped, or sw.js served with a one-year Cache-Control. Fix: network first for HTML; bump the version each deploy; short max-age on the worker file. Details in the caching guide.
12. Blank white page when offline
Cause: the fetch handler throws instead of returning the offline page, usually because offline.html wasn't precached or its path differs. Fix: precache it in install; in the catch branch, return caches.match('/offline.html') — and test in aeroplane mode.
13. Users see someone else's cart / account
Cause: personalised pages cached and served cache-first. Fix: exclude those paths from caching entirely. For shops, follow the exclusions on the WordPress page — they apply to any platform.
14. Mixed content breaks images or scripts
Cause: assets referenced over http:// on an HTTPS page; browsers block them, and inside an installed app there is no address-bar shield icon to hint why. Fix: search your HTML and CSS for http:// and use relative or HTTPS URLs.
Two that aren't bugs but feel like them
The cookie banner shows inside the app. It has to, on first launch, in most jurisdictions; the app is a fresh browsing context. Style it for a phone and make dismissal one tap.
The app doesn't update the instant I deploy. The browser checks sw.js at most once a day and activates new workers when tabs close. Implement the "refresh to update" banner from the offline guide if that matters to you.
Still stuck? Email us with the site URL and the exact DevTools installability message — that message is usually the answer.