google-gemini/gemini-cli · error · Error

Invalid environment variable value for "${key}". Values cann

Error message

Invalid environment variable value for "${key}". Values cannot contain newlines.

What it means

Thrown by formatEnvContent() when a setting value contains a newline (\n or \r). .env files are line-oriented, so an embedded newline would silently inject a second assignment and corrupt or exfiltrate configuration; the library rejects it rather than attempting escaping.

Source

Thrown at packages/cli/src/config/extensions/extensionSettings.ts:150

      throw new Error(
        `Cannot write extension settings to ${envFilePath} because it is a directory.`,
      );
    }
  }

  await fs.writeFile(envFilePath, envContent);
}

function formatEnvContent(settings: Record<string, string>): string {
  let envContent = '';
  for (const [key, value] of Object.entries(settings)) {
    if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {
      throw new Error(
        `Invalid environment variable name: "${key}". Must contain only alphanumeric characters and underscores.`,
      );
    }
    if (value.includes('\n') || value.includes('\r')) {
      throw new Error(
        `Invalid environment variable value for "${key}". Values cannot contain newlines.`,
      );
    }
    const formattedValue = value.includes(' ')
      ? `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`
      : value;
    envContent += `${key}=${formattedValue}\n`;
  }
  return envContent;
}

export async function promptForSetting(
  setting: ExtensionSetting,
): Promise<string | undefined> {
  const response = await prompts({
    type: setting.sensitive ? 'password' : 'text',
    name: 'value',
    message: `${setting.name}\n${setting.description}`,

View on GitHub (pinned to 5024443c72)

Solutions

  1. Strip newlines from the value before storing it, or encode it (e.g., base64) if line breaks are meaningful.
  2. Mark the setting as sensitive so it is stored in the keychain (sensitive settings bypass formatEnvContent).
  3. Split the multi-line value into multiple settings.

Example fix

// before
nonSensitiveSettings[envVar] = rawUserInput;  // rawUserInput has a trailing \n
// after
nonSensitiveSettings[envVar] = rawUserInput.replace(/[\r\n]+/g, '').trim();
Defensive patterns

Strategy: validation

Validate before calling

function assertSingleLine(key: string, value: string) {
  if (/\r|\n/.test(value)) throw new Error(`Value for ${key} contains newlines`);
}

Type guard

function isSingleLine(value: string): boolean { return !/[\r\n]/.test(value); }

Prevention

When it happens

Trigger: A user enters a multi-line value in a prompt, or a value is pasted from a file that includes a trailing CR/CRLF; the value is forwarded unchanged into nonSensitiveSettings and reaches formatEnvContent.

Common situations: Pasting private keys or certificates that contain newlines into a single-line prompt; Windows line endings (\r\n) in pasted text; JSON/multi-line tokens stored as a single setting.

Related errors


AI-assisted analysis of google-gemini/gemini-cli@5024443c72 (2026-08-12). Data as JSON: /api/errors/378cd9b78fba63bd. Report an issue: GitHub.