immich-app/immich · critical · Error

Invalid system config:

Error message

Invalid system config: 

What it means

Thrown by the config loader (server/src/utils/config.ts) when the raw system config fails Zod validation against SystemConfigSchema AND it was loaded from a config file (configFile set). The error message aggregates every Zod issue with its path and message. When there is no config file, validation errors are only logged, not thrown.

Source

Thrown at server/src/utils/config.ts:111

  const unknownKeys = _.cloneDeep(rawConfig);
  for (const property of getKeysDeep(defaults)) {
    unsetDeep(unknownKeys, property);
  }

  if (!_.isEmpty(unknownKeys)) {
    logger.warn(`Unknown keys found: ${JSON.stringify(unknownKeys, null, 2)}`);
  }

  // validate with Zod schema
  const result = SystemConfigSchema.safeParse(rawConfig);
  if (!result.success) {
    const messages = ['Invalid system config: '];
    for (const issue of result.error.issues) {
      const path = issue.path.join('.');
      messages.push(`  - [${path}] ${issue.message}`);
    }
    if (configFile) {
      throw new Error(messages.join('\n'));
    }
    logger.error('Validation error', messages);
  }

  const config = (result.success ? result.data : rawConfig) as SystemConfig;

  if (config.server.externalDomain.length > 0) {
    const domain = new URL(config.server.externalDomain);

    const externalDomain =
      domain.password && domain.username
        ? `${domain.protocol}//${domain.username}:${domain.password}@${domain.host}`
        : domain.origin;

    config.server.externalDomain = externalDomain;
  }

  if (!config.ffmpeg.acceptedVideoCodecs.includes(config.ffmpeg.targetVideoCodec)) {

View on GitHub (pinned to 199723261c)

Solutions

  1. Read the full error message — each line lists the field path and the Zod issue; fix each one in the config file.
  2. Compare your config file against the current SystemConfig schema/default template for the installed Immich version.
  3. Temporarily remove the config file to boot with DB-stored defaults, then re-apply changes field by field.
  4. Validate the file with a JSON/YAML linter before deploying.

Example fix

// before — config file
{ "ffmpeg": { "crf": -5 } }  // out of range

// after
{ "ffmpeg": { "crf": 23 } }
Defensive patterns

Strategy: validation

Validate before calling

// validate the config file against the same schema before boot
import { SystemConfigSchema } from 'src/...';
const raw = JSON.parse(readFileSync(configFile, 'utf8'));
const parsed = SystemConfigSchema.safeParse(raw);
if (!parsed.success) { for (const i of parsed.error.issues) console.error(i.path.join('.'), i.message); }

Type guard

const isSystemConfig = (v: unknown): v is SystemConfig => SystemConfigSchema.safeParse(v).success;

Try / catch

try { await loadConfig(); }
catch (e) { if (e instanceof Error && e.message.startsWith('Invalid system config')) { /* print issues, fall back to DB defaults */ } else throw e; }

Prevention

When it happens

Trigger: Immich started with IMMICH_CONFIG_FILE pointing at a JSON/YAML file whose values fail schema validation: wrong types, out-of-range numbers, unknown enum values, or structurally invalid nested objects.

Common situations: Editing the config file by hand and introducing a typo or invalid enum (e.g. ffmpeg.accel set to an unsupported hardware acceleration, or a negative CRF); upgrading Immich where a config field was renamed/removed and the old file no longer parses; copying a config snippet from an incompatible version.

Related errors


AI-assisted analysis of immich-app/immich@199723261c (2026-08-12). Data as JSON: /api/errors/30e4571678a6be52. Report an issue: GitHub.