vercel/turborepo · warning · Error

Config is invalid.

Error message

Config is invalid.

What it means

TelemetryConfig.validateConfig() parses a telemetry config object with a zod schema that requires telemetry_enabled (boolean), telemetry_id (string), telemetry_salt (string), with optional telemetry_alerted (string). Any mismatch throws this generic message and discards the underlying ZodError. In the normal read path (fromConfigPath) the error is caught and the corrupt telemetry.json is deleted and regenerated, so it only escapes when validateConfig is called directly.

Source

Thrown at packages/turbo-telemetry/src/config.ts:65

      return undefined;
    }
  }

  static async fromDefaultConfig(): Promise<TelemetryConfig | undefined> {
    try {
      const configPath = await utils.defaultConfigPath();
      return TelemetryConfig.fromConfigPath(configPath);
    } catch (e) {
      return undefined;
    }
  }

  static validateConfig(config: unknown): Config {
    try {
      return ConfigSchema.parse(config);
    } catch (e) {
      throw new Error("Config is invalid.");
    }
  }

  static create({
    configPath
  }: {
    configPath: string;
  }): TelemetryConfig | undefined {
    const RawTelemetryId = randomUUID();
    const telemetrySalt = randomUUID();
    const telemetryId = utils.oneWayHashWithSalt({
      input: RawTelemetryId,
      salt: telemetrySalt
    });

    const config = new TelemetryConfig({
      configPath,
      config: {

View on GitHub (pinned to 9f94a7d215)

Solutions

  1. Delete the telemetry config file (e.g. ~/.config/turborepo/telemetry.json, or wherever TURBO_CONFIG_DIR_PATH points) — Turborepo recreates it on the next run
  2. Fix the file to match the schema: { "telemetry_enabled": true, "telemetry_id": "<uuid>", "telemetry_salt": "<uuid>" } with booleans, not strings
  3. If calling validateConfig yourself, parse with the same zod schema first so you see the real validation issues

Example fix

// before (invalid: string instead of boolean)
{ "telemetry_enabled": "false", "telemetry_id": "abc" }

// after
{ "telemetry_enabled": false, "telemetry_id": "abc", "telemetry_salt": "def" }
Defensive patterns

Strategy: validation

Validate before calling

import { z } from "zod";

const TelemetrySchema = z.object({
  telemetry_enabled: z.boolean(),
  telemetry_id: z.string(),
  telemetry_salt: z.string(),
  telemetry_alerted: z.string().optional()
});

const parsed = TelemetrySchema.safeParse(rawConfig);
if (!parsed.success) console.error(parsed.error.issues); // real reason
else TelemetryConfig.validateConfig(parsed.data);

Type guard

const isTelemetryConfig = (c: unknown): c is { telemetry_enabled: boolean; telemetry_id: string; telemetry_salt: string; telemetry_alerted?: string } =>
  typeof c === "object" && c !== null &&
  typeof (c as any).telemetry_enabled === "boolean" &&
  typeof (c as any).telemetry_id === "string" &&
  typeof (c as any).telemetry_salt === "string";

Try / catch

try {
  TelemetryConfig.validateConfig(raw);
} catch (e) {
  if (e instanceof Error && e.message === "Config is invalid.") {
    // recover: delete config file and let TelemetryConfig.create regenerate it
  } else throw e;
}

Prevention

When it happens

Trigger: Calling TelemetryConfig.validateConfig(rawConfig) with an object that fails ConfigSchema.parse: missing or misspelled keys (telemetryId instead of telemetry_id), wrong types (telemetry_enabled: "true" instead of true), or a hand-edited file that is valid JSON but not valid telemetry config.

Common situations: Hand-editing ~/.config/turborepo/telemetry.json to disable telemetry with a string value; another tool truncating or rewriting the file; direct API use of validateConfig without pre-validation.

Related errors


AI-assisted analysis of vercel/turborepo@9f94a7d215 (2026-08-16). Data as JSON: /api/errors/aad2eecf61eadeed. Report an issue: GitHub.