immich-app/immich · error

Invalid telemetry found

Error message

Invalid telemetry found: ${telemetry}

What it means

IMMICH_TELEMETRY_INCLUDE/EXCLUDE are parsed into telemetry-name sets and each resulting value is validated against TELEMETRY_TYPES. If an included-minus-excluded telemetry name is not a known ImmichTelemetry value, startup throws with the invalid name.

Solutions

  1. Use only valid ImmichTelemetry values (see the enum in server/src): typically 'api', 'io', 'host' — set IMMICH_TELEMETRY_INCLUDE=all to enable everything instead of guessing names
  2. Fix casing/pluralization: IMMICH_TELEMETRY_INCLUDE=api,host
  3. If you meant OpenTelemetry-style tracing, that is not an immich telemetry kind — remove the token or use IMMICH_TELEMETRY_INCLUDE=all
  4. Check the enum for the installed immich version in case names changed

Example fix

// before
IMMICH_TELEMETRY_INCLUDE=metrics,tracing
// after
IMMICH_TELEMETRY_INCLUDE=all
# or
IMMICH_TELEMETRY_INCLUDE=api,io,host
Defensive patterns

Strategy: validation

Validate before calling

const TELEMETRY = new Set(['api', 'io', 'host']);
const include = process.env.IMMICH_TELEMETRY_INCLUDE;
if (include && include !== 'all') {
  const bad = include.split(',').filter(t => !TELEMETRY.has(t));
  if (bad.length) throw new Error(`Unknown telemetry: ${bad.join(',')} — valid: ${[...TELEMETRY].join(',')} or 'all'`);
}

Type guard

const isTelemetry = (t: string): t is 'api' | 'io' | 'host' => ['api', 'io', 'host'].includes(t);

Try / catch

try { start(); } catch (e) { if ((e as Error).message.startsWith('Invalid telemetry found:')) { console.error(`Use IMMICH_TELEMETRY_INCLUDE=all or valid kinds (api, io, host). ${(e as Error).message}`); process.exit(1); } throw e; }

Prevention

When it happens

Trigger: IMMICH_TELEMETRY_INCLUDE (or EXCLUDE after 'all' handling) contains a token not in the ImmichTelemetry enum, e.g. 'metrics', 'otel', 'tracing', or a case-mismatched 'API' instead of the valid values (e.g. 'api', 'io', 'host').

Common situations: Users enabling OpenTelemetry by guess-writing names; pluralizing ('hosts'); copying flags from another project's telemetry config; version drift where a telemetry kind was renamed or removed in immich.

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/5f99a1280bd7c937. Report an issue: GitHub.

Appendix: source

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

  const redisUrl = dto.REDIS_URL;
  if (redisUrl && redisUrl.startsWith('ioredis://')) {
    try {
      redisConfig = JSON.parse(Buffer.from(redisUrl.slice(10), 'base64').toString());
    } catch (error) {
      throw new Error('Failed to decode redis options', { cause: error });
    }
  }

  const includedTelemetries =
    dto.IMMICH_TELEMETRY_INCLUDE === 'all'
      ? new Set(Object.values(ImmichTelemetry))
      : asSet<ImmichTelemetry>(dto.IMMICH_TELEMETRY_INCLUDE, []);

  const excludedTelemetries = asSet<ImmichTelemetry>(dto.IMMICH_TELEMETRY_EXCLUDE, []);
  const telemetries = setDifference(includedTelemetries, excludedTelemetries);
  for (const telemetry of telemetries) {
    if (!TELEMETRY_TYPES.has(telemetry)) {
      throw new Error(`Invalid telemetry found: ${telemetry}`);
    }
  }

  const databaseConnection: DatabaseConnectionParams = dto.DB_URL
    ? { connectionType: 'url', url: dto.DB_URL }
    : {
        connectionType: 'parts',
        host: dto.DB_HOSTNAME || 'database',
        port: dto.DB_PORT || 5432,
        username: dto.DB_USERNAME || 'postgres',
        password: dto.DB_PASSWORD || 'postgres',
        database: dto.DB_DATABASE_NAME || 'immich',
        ssl: dto.DB_SSL_MODE || undefined,
      };

  let vectorExtension: VectorExtension | undefined;
  if (dto.DB_VECTOR_EXTENSION) {
    switch (dto.DB_VECTOR_EXTENSION) {

View on GitHub (pinned to e55ac299a4)