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
- Confirm the file exists: check public/poster_themes/<key>.json (or the packaged equivalent) is present on the deployed server
- Validate the key against the known theme list before calling loadTheme, and clamp to the default theme when unknown
- Rebuild/redeploy the container or asset pipeline so new theme JSON files ship
- 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
- Keep a manifest of shipped theme keys and validate user/URL-supplied keys against it
- Include /poster_themes/*.json in deploy verification (asset presence check) so missing files surface at rollout, not at user render time
- Cache the default theme eagerly so the fallback path never triggers a second network failure
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
- errorData.error || `Failed to ${isEdit ? "update" : "create"
- Failed to fetch points: ${response.statusText}
- Failed to create visit
- translate(ERROR_KEYS[body.error] || "poster.order_errors.gen
- [Onboarding] Failed to persist completion:
AI-assisted analysis of Freika/dawarich@97fad417c5 (2026-08-21).
Data as JSON: /api/errors/0b19607e4f369296.
Report an issue: GitHub.