Skip to content

Error pages support guide

Diagnostic and troubleshooting reference for the 404 and password page surfaces — 404 status code, per-preset hero SVG, recently-viewed, countdown timer setup, shop.password_message override, password page fonts, GDPR newsletter gating, and layout caveats. For merchant setup and configuration, see Error & password pages guide.


FAQ

Q1: My 404 page shows "200 OK" status in browser dev tools — is that a bug?

No. Shopify serves the correct HTTP 404 status code for bad URLs (verified via curl -I in 06.9-RESEARCH.md §Probe 1). However, browser DevTools shows the status code for the last request in a redirect chain — if Shopify does an internal redirect, you may see an intermediate 200.

Verify the actual status code:

bash
curl -I https://your-store.myshopify.com/not-a-real-path-12345
# Expected first line: HTTP/2 404

The Uisce theme also emits <meta name="robots" content="noindex,follow"> on 404 pages — inspect the page source to confirm:

bash
curl -s https://your-store.myshopify.com/not-a-real-path-12345 | grep 'robots'
# Expected: <meta name="robots" content="noindex,follow">

Q2: Countdown shows the wrong time — it's off by several hours

The opens_at setting stores an ISO 8601 datetime string. The most common cause of wrong display is entering a local time without a timezone offset (the Custom Element then interprets it as UTC).

Fix:

  1. Theme editor → Templates → Password → Opens at
  2. Enter your launch time in UTC using this format: YYYY-MM-DDTHH:MM:SSZ
  3. To convert from your timezone: subtract your UTC offset
    • IST (UTC+5:30): 9:00 AM IST = T03:30:00Z
    • EST (UTC-5): 9:00 AM EST = T14:00:00Z
    • GMT: 9:00 AM GMT = T09:00:00Z

Example:

2027-04-29T09:00:00Z    ← April 29 2027, 9:00 AM UTC

Still wrong after fixing the timezone? Hard-refresh the page (Ctrl+Shift+R) to clear the CDN cache and confirm the setting value was saved correctly in the theme editor.

Q3: Password page doesn't show fonts — text looks like browser defaults

Phase 06.9 added {% render 'fonts' %} to layout/password.liquid (D-38). If you are on an earlier Uisce theme version, the password page may be missing the font preload.

Verify the font snippet is rendering:

bash
curl -s https://your-store.myshopify.com/password | grep 'preload'
# Expected: rel="preload" as="font" ...

If preload is missing, you may be running a pre-06.9 version of the theme. Push the updated theme via scripts/push-presets.sh.

If you're on 06.9+ and fonts still don't render: Check the browser Network tab — filter by font — the theme's font files should load with HTTP 200.

This is a Shopify platform constraint (D-31), not a theme behavior. When a visitor lands on a password-protected store at e.g. /collections/new, then enters the password, Shopify redirects them to / (the homepage) — not back to /collections/new.

This is standard Shopify behavior across all themes. There is no theme-side workaround — Shopify does not pass the original URL through the password form POST.

If deep-link preservation is critical to your use case: Consider using Shopify's locksmith app or similar, which can implement deep-link preservation via server-side session management.

If the checkbox is not visible: Confirm show_newsletter_block is ON in the password section settings AND the newsletter block's show_gdpr_checkbox setting is ON (default: ON).

If the form submits without checking the checkbox: This is a browser bug — the theme marks the checkbox as required. Test in a fresh browser profile or disable extensions that may be auto-filling forms.

To verify the checkbox is required:

Run the console snippet below → inspect password.newsletter — if true, the <customer-form> element is present. Then inspect in DevTools:

javascript
document.querySelector('.password-page__newsletter input[type="checkbox"]').required;
// Expected: true

Console diagnostic snippet

Paste into Chrome DevTools console (F12 → Console tab) on any page of the live store. Reports footer state always; also reports 404 state when on a 404 page, password state on the password page, and gift-card state on a gift-card page.

js
(function () {
  var path = location.pathname;
  var report = { path: path, surfaces: {} };
  // Footer always
  var footer = document.querySelector('.footer');
  report.surfaces.footer = {
    present: !!footer,
    policies: !!document.querySelector('.footer__policies'),
    localization: !!document.querySelector('.footer__localization'),
    newsletter: !!document.querySelector('.footer__newsletter-block customer-form'),
    payment_icons_aria: Array.from(document.querySelectorAll('.footer__payment span[aria-label]')).length,
  };
  // 404
  if (document.querySelector('.section-404')) {
    report.surfaces['404'] = {
      hero: !!document.querySelector('.section-404__hero svg'),
      search: !!document.querySelector('.section-404__search'),
      recently_viewed: !!document.querySelector('recently-viewed'),
      noindex: document.querySelector('meta[name="robots"]')
        ? document.querySelector('meta[name="robots"]').content
        : null,
    };
  }
  // Password
  if (document.querySelector('.password-page')) {
    report.surfaces.password = {
      logo: !!document.querySelector('.password-page__logo img'),
      hero: !!document.querySelector('.password-page__hero svg'),
      countdown: !!document.querySelector('count-down'),
      newsletter: !!document.querySelector('.password-page__newsletter customer-form'),
      social: !!document.querySelector('.password-page__social'),
      localization: !!document.querySelector('.password-page__localization'),
    };
  }
  // Gift-card
  if (document.querySelector('.gift-card-page')) {
    report.surfaces.gift_card = {
      qr: !!document.querySelector('gift-card-qr canvas'),
      copy: !!document.querySelector('gift-card-copy'),
      balance: document.querySelector('.gift-card-page__balance')
        ? document.querySelector('.gift-card-page__balance').textContent.trim()
        : null,
      state:
        ['active', 'expired', 'depleted'].filter(function (s) {
          return !!document.querySelector('.gift-card-page--state-' + s);
        })[0] || 'active',
      apple_wallet: !!document.querySelector('.gift-card-page__apple-wallet'),
      google_wallet: !!document.querySelector('.gift-card-page__google-wallet'),
    };
  }
  console.table(report.surfaces);
  return report;
})();

What to look for on a 404 page:

  • surfaces['404'].hero === true — 404 hero SVG is inlined
  • surfaces['404'].search === true — search form is rendering
  • surfaces['404'].recently_viewed === true<recently-viewed> element is present (requires prior browsing history in localStorage)
  • surfaces['404'].noindex === "noindex,follow" — meta robots tag is emitting correctly

What to look for on the password page:

  • surfaces.password.logo === truesettings.logo is rendering
  • surfaces.password.hero === true — per-preset hero SVG is inlined
  • surfaces.password.countdown === true<count-down> element is present (requires opens_at to be set and in the future)
  • surfaces.password.newsletter === true — newsletter block with <customer-form> is present

Curl cheat-sheet (D-67)

bash
curl -L -s -o /dev/null -w "%{http_code}" https://your-store.myshopify.com/policies/privacy-policy
# Expected: 200

Topic 2 — 404 status code verification

bash
curl -I https://your-store.myshopify.com/not-a-real-path-12345
# Expected: HTTP/2 404

The HTTP 404 status is served by Shopify for all bad URLs — this is the primary SEO signal. The Uisce theme adds a <meta name="robots" content="noindex,follow"> as a defense-in-depth layer.

Topic 3 — Password form action verification

bash
curl -I https://your-store.myshopify.com/password
# Expected: HTTP/2 200

Inspect the form action on a live password page:

bash
curl -s -b cookies.txt https://your-store.myshopify.com/password | grep 'form action'
# Expected: <form method="post" action="/password">

Topic 4 — Gift-card noindex,nofollow header (for reference)

bash
curl -I https://your-store.myshopify.com/gift_cards/{code}
# Expected: x-robots-tag: noindex, nofollow (Shopify platform header)

Topic 5 — Apple Wallet pass URL (for reference)

bash
curl -I {apple_wallet_pass_url}
# Expected: HTTP/2 200

Topic 6 — Google Wallet template substitution (for reference)

bash
curl -s https://your-store.myshopify.com/gift_cards/{code} | grep google-wallet
# Expected: href with substituted code and amount values

Topic 7 — Cache-control for error-page assets

bash
curl -I https://your-store.myshopify.com/cdn/shop/t/1/assets/error-pages.css
# Expected: cache-control: public, max-age=31536000 (Shopify CDN strong cache)

Built for the Shopify Theme Store.