{"record":{"id":"16404d85ee1837a4","repo":"google-gemini/gemini-cli","slug":"invalid-environment-variable-name-key-must","errorCode":null,"errorMessage":"Invalid environment variable name: \"${key}\". Must contain only alphanumeric characters and underscores.","messagePattern":"Invalid environment variable name: \"(.+?)\"\\. Must contain only alphanumeric characters and underscores\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/config/extensions/extensionSettings.ts","lineNumber":145,"sourceCode":"  const envContent = formatEnvContent(nonSensitiveSettings);\n\n  if (fsSync.existsSync(envFilePath)) {\n    const stat = fsSync.statSync(envFilePath);\n    if (stat.isDirectory()) {\n      throw new Error(\n        `Cannot write extension settings to ${envFilePath} because it is a directory.`,\n      );\n    }\n  }\n\n  await fs.writeFile(envFilePath, envContent);\n}\n\nfunction formatEnvContent(settings: Record<string, string>): string {\n  let envContent = '';\n  for (const [key, value] of Object.entries(settings)) {\n    if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key)) {\n      throw new Error(\n        `Invalid environment variable name: \"${key}\". Must contain only alphanumeric characters and underscores.`,\n      );\n    }\n    if (value.includes('\\n') || value.includes('\\r')) {\n      throw new Error(\n        `Invalid environment variable value for \"${key}\". Values cannot contain newlines.`,\n      );\n    }\n    const formattedValue = value.includes(' ')\n      ? `\"${value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')}\"`\n      : value;\n    envContent += `${key}=${formattedValue}\\n`;\n  }\n  return envContent;\n}\n\nexport async function promptForSetting(\n  setting: ExtensionSetting,","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/google-gemini/gemini-cli/blob/5024443c7217464a66e98f80d73172a26440bd8f/packages/cli/src/config/extensions/extensionSettings.ts#L127-L163","documentation":"Thrown by formatEnvContent() when an environment variable name (key) fails the regex /^[a-zA-Z_][a-zA-Z0-9_]*$/. The library writes a .env-style file, so keys must be valid shell identifiers; any other character set would produce an unparseable or insecure env file.","triggerScenarios":"An extension declares a setting whose envVar contains characters outside [A-Za-z0-9_], starts with a digit, or is empty. The formatter iterates Object.entries(nonSensitiveSettings) and validates every key.","commonSituations":"A migration config uses keys with dashes (my-var), dots (section.key), or spaces; a typo in the extension manifest envVar; generated keys from user input that were not sanitized.","solutions":["Rename the offending envVar in the extension setting definition to a valid identifier (letters, digits, underscores; not starting with a digit).","Sanitize keys before they reach writeExtensionSettings: replace invalid characters with underscores.","Add a manifest validator that rejects invalid envVar names at extension load time."],"exampleFix":"// before\nenvVar: 'my-extension.key'\n// after\nenvVar: 'MY_EXTENSION_KEY'","handlingStrategy":"validation","validationCode":"const ENV_VAR_RE = /^[a-zA-Z_][a-zA-Z0-9_]*$/;\nfunction sanitizeEnvVar(name: string): string {\n  return name.replace(/[^a-zA-Z0-9_]/g, '_').replace(/^[0-9]/, '_$1');\n}\nfunction assertValidEnvVar(name: string) {\n  if (!ENV_VAR_RE.test(name)) throw new Error(`Invalid env var name: ${name}`);\n}","typeGuard":"function isValidEnvVarName(name: string): boolean { return /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name); }","tryCatchPattern":null,"preventionTips":["Validate envVar names in the extension manifest loader so bad names never reach the writer.","Generate envVar names from a fixed allow-list of characters."],"tags":["extensions","settings","validation","env","config"],"backgroundTag":null,"analyzedSha":"5024443c7217464a66e98f80d73172a26440bd8f","analyzedAt":"2026-08-12T06:01:53.711Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}