{"record":{"id":"0f964028870a2eb3","repo":"google-gemini/gemini-cli","slug":"cannot-write-extension-settings-to-envfilepath","errorCode":null,"errorMessage":"Cannot write extension settings to ${envFilePath} because it is a directory.","messagePattern":"Cannot write extension settings to (.+?) because it is a directory\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/config/extensions/extensionSettings.ts","lineNumber":132,"sourceCode":"  const nonSensitiveSettings: Record<string, string> = {};\n  for (const setting of settings) {\n    const value = allSettings[setting.envVar];\n    if (value === undefined || value === '') {\n      continue;\n    }\n    if (setting.sensitive) {\n      await keychain.setSecret(setting.envVar, value);\n    } else {\n      nonSensitiveSettings[setting.envVar] = value;\n    }\n  }\n\n  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(","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/google-gemini/gemini-cli/blob/5024443c7217464a66e98f80d73172a26440bd8f/packages/cli/src/config/extensions/extensionSettings.ts#L114-L150","documentation":"Thrown by the bulk write path (saveExtensionSettings / formatEnvContent caller) when the target env file path already exists and is a directory. The code stat()s envFilePath before fs.writeFile and refuses to overwrite a directory, because writing a file over a folder would either fail or corrupt the layout.","triggerScenarios":"A directory named EXTENSION_SETTINGS_FILENAME (e.g. .env) already exists at the location returned by getEnvFilePath (workspace dir or ExtensionStorage env file path). Reached when writing all non-sensitive extension settings at once.","commonSituations":"A user or script manually created a folder named like the env settings file; a previous tooling bug created a directory where a file was expected; a symlink loop resolves to a directory.","solutions":["Inspect envFilePath and remove or rename the directory blocking the write.","Change the storage location so the settings file does not collide with an existing directory.","Add a pre-write stat check in the caller and surface a clearer prompt before this throw."],"exampleFix":"// before\nawait fs.writeFile(envFilePath, envContent);  // throws if envFilePath is a dir\n// after\nif (fsSync.existsSync(envFilePath) && fsSync.statSync(envFilePath).isDirectory()) {\n  throw new Error(`Refusing to overwrite directory at ${envFilePath}; remove it first.`);\n}\nawait fs.writeFile(envFilePath, envContent);","handlingStrategy":"validation","validationCode":"import fsSync from 'node:fs';\nfunction ensureWritableFile(envFilePath: string) {\n  if (fsSync.existsSync(envFilePath) && fsSync.statSync(envFilePath).isDirectory()) {\n    throw new Error(`${envFilePath} is a directory, not a writable file`);\n  }\n}","typeGuard":null,"tryCatchPattern":"try { await saveExtensionSettings(...); } catch (e) { if (String(e).includes('because it is a directory')) { /* prompt user to remove dir */ } throw e; }","preventionTips":["Treat the settings file location as reserved; never create directories with the same name.","Run a stat-check before bulk write in your own wrapper to give a clearer message."],"tags":["extensions","settings","filesystem","config"],"backgroundTag":null,"analyzedSha":"5024443c7217464a66e98f80d73172a26440bd8f","analyzedAt":"2026-08-12T06:01:53.711Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}