Freika/dawarich · warning · Error

Failed to load poster theme "${key}" (${response.status})

Error message

Failed to load poster theme "${key}" (${response.status})

What it means

Poster Studio lazily fetches theme token JSON from the static route /poster_themes/{key}.json (two-level cache: tokenCache then resolved-theme cache). Any non-OK status throws with the HTTP code baked into the message: 404 means the theme key has no JSON asset, 401/403 mean the route sits behind auth, 500 means the web server failed to serve the file. Because the throw happens inside loadThemeTokens, loadTheme and every dependent render also fail.

Source

Thrown at app/javascript/poster_studio/data/theme_loader.js:82

      primary: tokens.road_primary,
      secondary: tokens.road_secondary,
      tertiary: tokens.road_tertiary,
      residential: tokens.road_residential,
      default: tokens.road_default,
    },
    route: tokens.route ?? DEFAULT_ROUTE_COLOR,
    casing: tokens.bg ?? DEFAULT_CASING_COLOR,
  }
}

const cache = new Map()
const tokenCache = new Map()

export async function loadThemeTokens(key) {
  if (tokenCache.has(key)) return tokenCache.get(key)
  const response = await fetch(`/poster_themes/${key}.json`)
  if (!response.ok) {
    throw new Error(`Failed to load poster theme "${key}" (${response.status})`)
  }
  const tokens = await response.json()
  tokenCache.set(key, tokens)
  return tokens
}

export async function loadTheme(key) {
  if (cache.has(key)) return cache.get(key)
  const resolved = resolveTheme(await loadThemeTokens(key))
  cache.set(key, resolved)
  return resolved
}

View on GitHub (pinned to 97fad417c5)

Solutions

  1. Confirm the file exists: check public/poster_themes/<key>.json (or the packaged equivalent) is present on the deployed server
  2. Validate the key against the known theme list before calling loadTheme, and clamp to the default theme when unknown
  3. Rebuild/redeploy the container or asset pipeline so new theme JSON files ship
  4. Wrap loadTheme callers with a fallback to the default theme so one bad key cannot break the whole poster editor

Example fix

// before
const resolved = resolveTheme(await loadThemeTokens(key))

// after
let tokens
try {
  tokens = await loadThemeTokens(key)
} catch {
  tokens = await loadThemeTokens(DEFAULT_THEME_KEY)
}
const resolved = resolveTheme(tokens)
Defensive patterns

Strategy: fallback

Validate before calling

const KNOWN_THEMES = new Set(['light', 'dark', 'topographic']) // keep in sync with shipped assets
function isKnownTheme(key) {
  return KNOWN_THEMES.has(key)
}
// before loadTheme:
const safeKey = isKnownTheme(key) ? key : DEFAULT_THEME_KEY

Try / catch

try {
  theme = await loadTheme(key)
} catch (error) {
  console.warn(`Theme '${key}' failed to load (${error.message}); using default`) 
  theme = await loadTheme(DEFAULT_THEME_KEY)
}

Prevention

When it happens

Trigger: loadTheme('dark') where public/poster_themes/dark.json was never shipped; a theme key read from a saved poster or URL param that was renamed; the asset missing from a Docker image because it was added after the image build; a CDN/proxy misroute returning 404 for static JSON.

Common situations: Deploying new themes without recompiling/copying static assets, users following old share links with retired theme keys, theme key typos in configuration, serving /poster_themes from a different host that requires auth headers.

Related errors


AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21). Data as JSON: /api/errors/0b19607e4f369296. Report an issue: GitHub.