musistudio/claude-code-router · error · Error

Invalid theme preference.

Error message

Invalid theme preference.

What it means

normalizeAppThemePreference only accepts the literal strings 'system', 'light', or 'dark'; any other value (including undefined/null/numbers) throws when normalizing app config.

Source

Thrown at packages/core/src/config/config.ts:411

  const normalizedConfig = withSingleEnabledGlobalProfiles(config);
  assertProviderApiKeysAreSafe(normalizedConfig);
  const apiKeys = ensureGatewayApiKeys(normalizeApiKeys(normalizedConfig.APIKEYS, normalizedConfig.APIKEY).filter((apiKey) => !isDefaultSeedApiKey(apiKey)));
  const pluginMigration = migrateKnownGatewayPluginConfigs(normalizedConfig.plugins);
  await replacePersistedConfigSnapshot(sanitizeConfigForDisk({
    ...normalizedConfig,
    theme: appThemePreferenceOverride ?? normalizedConfig.theme,
    APIKEY: apiKeys[0]?.key ?? "",
    APIKEYS: apiKeys,
    plugins: pluginMigration.plugins
  }), apiKeys);
  return loadAppConfig();
}

function normalizeAppThemePreference(theme: unknown): AppConfig["theme"] {
  if (theme === "system" || theme === "light" || theme === "dark") {
    return theme;
  }
  throw new Error("Invalid theme preference.");
}

function enqueueAppConfigWrite<T>(operation: () => Promise<T>): Promise<T> {
  const result = appConfigWriteQueue.then(operation, operation);
  appConfigWriteQueue = result.then(
    () => undefined,
    () => undefined
  );
  return result;
}

function withSingleEnabledGlobalProfiles(config: AppConfig): AppConfig {
  const profiles = enforceSingleEnabledGlobalProfilePerAgent(config.profile.profiles);
  return {
    ...config,
    Providers: config.Providers.map(normalizeProviderPresetCapabilities),
    profile: synchronizeLegacyProfileConfig({
      ...config.profile,

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Set theme to "system", "light", or "dark" in the config file.
  2. Sanitize before saving: coerce unknown values to "system".
  3. Re-save config from the app's settings UI to rewrite a valid value.

Example fix

// before
theme: config.theme // may be "Dark"
// after
theme: ["system","light","dark"].includes(config.theme) ? config.theme : "system"
Defensive patterns

Strategy: type-guard

Validate before calling

if (!['system','light','dark'].includes(cfg.theme)) cfg.theme = 'system';

Type guard

function isAppTheme(v: unknown): v is 'system' | 'light' | 'dark' {
  return v === 'system' || v === 'light' || v === 'dark';
}

Try / catch

catch (e) { if ((e as Error).message === 'Invalid theme preference.') { config.theme = 'system'; await save(config); } }

Prevention

When it happens

Trigger: Loading/saving app config where theme is not one of the three accepted literals — e.g. hand-edited config file, config written by an older/newer version, or a UI writing a raw enum.

Common situations: User edits config.json and types "Dark" or "auto"; migration writes theme: null.

Related errors


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/44838dc8270bed8a. Report an issue: GitHub.