immich-app/immich · error

Invalid worker(s) found

Error message

Invalid worker(s) found: ${workers.join(',')}

What it means

After parsing IMMICH_WORKERS_INCLUDE/EXCLUDE into a set of worker names, getEnv verifies each resulting worker is a known ImmichWorker. If any computed worker is not in WORKER_TYPES, startup aborts with the comma-separated list of all offending workers.

Solutions

  1. Use only valid worker names: 'api' and 'microservices' (check the ImmichWorker enum in server/src for the exact set)
  2. Fix casing/spelling: IMMICH_WORKERS_INCLUDE=api,microservices (lowercase, no spaces)
  3. If the intent was to exclude a worker, set IMMICH_WORKERS_EXCLUDE=microservices instead of inventing names in INCLUDE
  4. Upgrade/downgrade immich if a worker name existed in another version of the enum

Example fix

// before
IMMICH_WORKERS_INCLUDE=api,worker
// after
IMMICH_WORKERS_INCLUDE=api,microservices
Defensive patterns

Strategy: validation

Validate before calling

const WORKERS = new Set(['api', 'microservices']);
const requested = (process.env.IMMICH_WORKERS_INCLUDE ?? 'api,microservices').split(',').filter(Boolean);
const bad = requested.filter(w => !WORKERS.has(w));
if (bad.length) throw new Error(`Unknown workers: ${bad.join(',')} — valid: ${[...WORKERS].join(',')}`);

Type guard

const isWorker = (w: string): w is 'api' | 'microservices' => w === 'api' || w === 'microservices';

Try / catch

try { start(); } catch (e) { if ((e as Error).message.startsWith('Invalid worker(s) found')) { console.error(`Valid workers are: api, microservices. Got: ${(e as Error).message}`); process.exit(1); } throw e; }

Prevention

When it happens

Trigger: IMMICH_WORKERS_INCLUDE or IMMICH_WORKERS_EXCLUDE contains a value not in the ImmichWorker enum (e.g. 'api,worker', 'microservice', case-mismatched 'API'), so the set difference produces an unknown worker name.

Common situations: Users writing '-worker' or 'jobs' expecting background jobs; pluralizing 'microservices'; renaming after an immich version changed the worker enum; including an excluded-only name or an entirely wrong token in the comma list.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of immich-app/immich@e55ac299a4 (2026-09-15). Data as JSON: /api/errors/44311465910e1622. Report an issue: GitHub.

Appendix: source

Thrown at server/src/repositories/config.repository.ts:186

const getEnv = (): EnvData => {
  const parseResult = EnvSchema.safeParse(process.env);
  if (!parseResult.success) {
    const messages = ['Invalid environment variables: '];
    for (const issue of parseResult.error.issues) {
      const path = issue.path.join('.');
      messages.push(`  - [${path}] ${issue.message}`);
    }
    throw new Error(messages.join('\n'));
  }
  const dto = parseResult.data;

  const includedWorkers = asSet(dto.IMMICH_WORKERS_INCLUDE, [ImmichWorker.Api, ImmichWorker.Microservices]);
  const excludedWorkers = asSet(dto.IMMICH_WORKERS_EXCLUDE, []);
  const workers = [...setDifference(includedWorkers, excludedWorkers)];
  for (const worker of workers) {
    if (!WORKER_TYPES.has(worker)) {
      throw new Error(`Invalid worker(s) found: ${workers.join(',')}`);
    }
  }

  const environment = dto.IMMICH_ENV || ImmichEnvironment.Production;
  const isProd = environment === ImmichEnvironment.Production;
  const buildFolder = dto.IMMICH_BUILD_DATA || '/build';
  const folders = {
    geodata: join(buildFolder, 'geodata'),
    web: join(buildFolder, 'www'),
  };

  let redisConfig = {
    host: dto.REDIS_HOSTNAME || 'redis',
    port: dto.REDIS_PORT || 6379,
    db: dto.REDIS_DBINDEX || 0,
    username: dto.REDIS_USERNAME || undefined,
    password: dto.REDIS_PASSWORD || undefined,
    path: dto.REDIS_SOCKET || undefined,

View on GitHub (pinned to e55ac299a4)