JosefNemec/Playnite · error · Exception

Extension already exists: {outDir}

Error message

Extension already exists: {outDir}

What it means

Thrown by Toolbox.Extensions.GenerateScriptExtension when the target output directory (directory + normalized script name) already exists. The generator refuses to overwrite an existing extension to avoid clobbering prior work, so it hard-throws.

Source

Thrown at source/Tools/Playnite.Toolbox/Extensions.cs:77

            for (int i = 0; i < input.Length; i++)
            {
                var chr = input[i];
                if (isValidInIdentifier(chr, i == 0))
                {
                    sb.Append(chr);
                }
            }

            return sb.ToString();
        }

        public static string GenerateScriptExtension(string name, string directory)
        {
            var normalizedName = ConvertToValidIdentifierName(name);
            var outDir = Path.Combine(directory, normalizedName);
            if (Directory.Exists(outDir))
            {
                throw new Exception($"Extension already exists: {outDir}");
            }

            var templateArchive = Path.Combine(PlaynitePaths.ProgramPath, "Templates", "Extensions", "PowerShellScript.zip"); ;
            ZipFile.ExtractToDirectory(templateArchive, outDir);
            var pluginId = Guid.NewGuid();
            foreach (var filePath in Directory.GetFiles(outDir, "*.*", SearchOption.AllDirectories))
            {
                var changed = false;
                var fileContent = File.ReadAllText(filePath, Encoding.UTF8);
                if (fileContent.Contains(nameReplaceMask))
                {
                    fileContent = fileContent.Replace(nameReplaceMask, normalizedName);
                    changed = true;
                }

                if (fileContent.Contains(guidReplaceMask))
                {
                    fileContent = fileContent.Replace(guidReplaceMask, pluginId.ToString());

View on GitHub (pinned to 5911f4e964)

Solutions

  1. Choose a different extension name whose normalized identifier does not collide.
  2. Move or delete the existing outDir before regenerating.
  3. Generate into a different parent `directory`.
  4. If the existing folder is a leftover from a failed run, remove it and retry.

Example fix

// before
Extensions.GenerateScriptExtension("MyAddon", @"C:\dev"); // C:\dev\MyAddon exists -> throws

// after
Extensions.GenerateScriptExtension("MyAddonV2", @"C:\dev"); // new dir
// or: Directory.Delete(@"C:\dev\MyAddon", true); first
Defensive patterns

Strategy: validation

Validate before calling

var outDir = Path.Combine(directory, ConvertToValidIdentifierName(name));
if (Directory.Exists(outDir))
    throw new InvalidOperationException($"Refusing to overwrite existing extension dir: {outDir}");
// or: pick a unique suffix

Type guard

static bool CanScaffoldScriptExtension(string name, string directory) => !Directory.Exists(Path.Combine(directory, ConvertToValidIdentifierName(name)));

Try / catch

try { return Extensions.GenerateScriptExtension(name, directory); }
catch (Exception ex) when (ex.Message.StartsWith("Extension already exists")) { /* prompt user to overwrite or rename */ }

Prevention

When it happens

Trigger: Running `playnite-toolbox new` (or GenerateScriptExtension directly) with a name whose ConvertToValidIdentifierName normalization collides with an existing subdirectory under `directory` (Directory.Exists(outDir) true at line 75).

Common situations: Re-running the scaffolder with the same extension name in the same parent folder. A previous partial run left the directory behind. Two names that normalize to the same identifier (e.g. 'MyAddon' and 'My Addon' both -> 'MyAddon').

Related errors


AI-assisted analysis of JosefNemec/Playnite@5911f4e964 (2026-08-13). Data as JSON: /api/errors/0abd91ef2959e041. Report an issue: GitHub.