Skip to content

Error pages support guide

Component reference: the live component pages are 404 page and Password page.

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, the newsletter signup block, 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 countdown target is set with the Year / Month / Day / Time dropdowns in the password section settings (the Time dropdown steps in 30-minute increments; the fields appear once Show countdown is on). The section composes them into a YYYY-MM-DD HH:MM string, and the <count-down> element parses that with the browser's Date constructor — an offset-less string like this is interpreted in each visitor's local timezone, not UTC.

What that means:

  • The countdown reaches zero at the chosen wall-clock time in each visitor's own timezone — a visitor in Dublin and a visitor in New York each see it end at 9:00 AM their local time.
  • If the display looks "off by several hours", you are most likely comparing against a different timezone than the browser you are testing in.

Fix:

  1. Theme editor → Password template → password section → set Year / Month / Day / Time to your intended launch time — think of it as your store's wall-clock time.
  2. Test in a browser set to your store's timezone to see what local shoppers will see.

A hidden legacy opens_at ISO field exists for back-compat with older configurations; it is not reachable in the theme editor. If a full ISO value with a Z or offset suffix was stored there historically, the browser honors that offset instead of local time.

Still wrong after fixing the time? Hard-refresh the page (Ctrl+Shift+R) to bypass your browser 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, first check whether the theme's body and heading fonts are set to system fonts in Theme Settings → Typography — the theme emits no font preload for system fonts (they need no download, and browser-default rendering is then expected). If custom fonts are selected and preload is still missing, you may be running a pre-06.9 version of the theme. Update it via the safe default — it preserves live settings and deletes nothing:

bash
bash scripts/sync-theme-safe.sh <Preset>

scripts/push-presets.sh is the destructive full-reset path (overwrites live settings with committed defaults) — use it only per docs/deploy/RUNBOOK.md.

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.

There is none, by design. The form is single-purpose (email signup only), so subscribing IS the consent: it submits a hidden contact[accepts_marketing] field set to true, and the "Unsubscribe anytime." line below the form carries the reassurance. Only the email input is required.

If the newsletter block is missing entirely: Confirm show_newsletter_block is ON in the password section settings.

To verify the block is rendering:

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

javascript
!!document.querySelector('.password-page__newsletter customer-form');
// 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 (server-rendered whenever the recently-viewed toggle is on; it stays hidden until stored browsing history exists, but its presence never depends on history)
  • 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 (renders whenever Show countdown is on and an opening date is set — past dates render too, clamped to zero)
  • 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 -o 'action="/password"'
# Expected: 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.