Skip to content
Twilight React Playground
ثيم رائدaren

SettingsError

classAdvancedserverbrowser

The error thrown when a request has no store settings; left uncaught at the root it becomes the "Store Unavailable" page.

import { SettingsError } from '@salla.sa/twilight-theme-engine';

In plain words

Every page needs the store's settings first. When the engine cannot get them (an unknown store, the API not answering, code running outside a request), it throws a SettingsError.

Checking error instanceof SettingsError tells that case apart from a bug in your own code.

Signature

class SettingsError extends Error {
  constructor(message?: string);   // default 'Store settings could not be loaded.'
  name: 'SettingsError';
}

Example

app/lib/store-title.ts
import { SettingsError } from '@salla.sa/twilight-theme-engine';
import { getTwilightContext } from '@salla.sa/twilight-theme-engine/tanstack';

// Safe in a head function: settings may be missing while the page hydrates.
export function storeTitle(fallback = 'Store'): string {
  try {
    return getTwilightContext().settings.store?.name ?? fallback;
  } catch (error) {
    if (error instanceof SettingsError) return fallback;
    throw error;
  }
}

How it behaves

  • Thrown by the settings getter of getTwilightContext() (and so of useTwilight()) when the context holds no settings, and by the root route's beforeLoad when the settings request returned nothing, with the message "Failed to load store settings. Make sure VITE_STORE_DOMAIN is set."

  • The root route's error component then renders the "Store is temporarily unavailable" page, and the root head falls back to the title "Store Unavailable". withHead() from /tanstack catches it and drops that route's head tags.

  • Also exported from /providers.

Gotchas

  • Never let it escape a head function. A throw there during hydration makes React discard the server HTML and the storefront renders blank (the reason withHead catches it, src/tanstack/head.ts). Guard direct reads of settings in head code as the example does.

Related

Source and docs