{"record":{"id":"329375fc78f0e9af","repo":"google-gemini/gemini-cli","slug":"invalid-extension-name-name-only-letters-a-z-a-z-numbers-0-9","errorCode":null,"errorMessage":"Invalid extension name: \"${name}\". Only letters (a-z, A-Z), numbers (0-9), and dashes (-) are allowed.","messagePattern":"Invalid extension name: \"(.+?)\"\\. Only letters \\(a-z, A-Z\\), numbers \\(0-9\\), and dashes \\(-\\) are allowed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/config/extension-manager.ts","lineNumber":1404,"sourceCode":"\n      if (!validation.isValid) {\n        debugLogger.warn(\n          `[ExtensionManager] Invalid contextFileName: \"${contextFileName}\" in extension \"${config.name}\". ${validation.errorMessage}`,\n        );\n        return null;\n      }\n\n      return validation.resolvedPath!;\n    })\n    .filter(\n      (contextFilePath): contextFilePath is string =>\n        contextFilePath !== null && fs.existsSync(contextFilePath),\n    );\n}\n\nfunction validateName(name: string) {\n  if (!/^[a-zA-Z0-9-]+$/.test(name)) {\n    throw new Error(\n      `Invalid extension name: \"${name}\". Only letters (a-z, A-Z), numbers (0-9), and dashes (-) are allowed.`,\n    );\n  }\n}\n\nexport async function inferInstallMetadata(\n  source: string,\n  args: {\n    ref?: string;\n    autoUpdate?: boolean;\n    allowPreRelease?: boolean;\n  } = {},\n): Promise<ExtensionInstallMetadata> {\n  if (\n    source.startsWith('http://') ||\n    source.startsWith('https://') ||\n    source.startsWith('git@') ||\n    source.startsWith('sso://') ||","sourceCodeStart":1386,"sourceCodeEnd":1422,"githubUrl":"https://github.com/google-gemini/gemini-cli/blob/6a466a7e2fe2b1255752c1e74f69b31f0216084d/packages/cli/src/config/extension-manager.ts#L1386-L1422","documentation":"The extension manager validates extension names with the regex /^[a-zA-Z0-9-]+$/ in validateName before performing install/lookup operations. Any name containing characters outside letters, digits, and dashes (spaces, underscores, dots, slashes, unicode) is rejected. This keeps names safe to embed in file paths, registry URLs, and CLI flags.","triggerScenarios":"Calling inferInstallMetadata (or any extension install/lookup path) with a name argument that fails validateName's regex, e.g. a git URL, a scoped npm-style name like '@scope/pkg', or a name with '_' or '.'.","commonSituations":"Users pass a GitHub repo URL instead of the plain repo name, use underscores instead of dashes ('my_ext'), or a config file / registry entry contains a malformed extension name.","solutions":["Sanitize the name to only [a-zA-Z0-9-], replacing invalid characters with dashes, before invoking the install command.","If installing from a URL or subdirectory, extract just the base name (e.g. 'my-extension' from 'https://github.com/user/my-extension.git').","Fix the extension's metadata/config file so its name field matches the allowed pattern."],"exampleFix":"// before\ngemini extensions install https://github.com/user/my_ext.git\n// after\ngemini extensions install my-ext","handlingStrategy":"validation","validationCode":"if (!/^[a-zA-Z0-9-]+$/.test(name)) {\n  throw new Error(`Invalid extension name: ${name}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Normalize names with name.replace(/[^a-zA-Z0-9-]/g, '-') before installing.","Strip URL/protocol prefixes and extract the repo base name first.","Validate names in config files with a schema (pattern constraint) at load time."],"tags":["cli","validation","naming"],"backgroundTag":"invalid-identifier-format","analyzedSha":"6a466a7e2fe2b1255752c1e74f69b31f0216084d","analyzedAt":"2026-09-16T18:14:43.978Z","contentChangedAt":"2026-09-16T18:14:43.978Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}