swc-project/swc · error

destination ` ` already exists

Error message

destination `{}` already exists

What it means

`swc plugin new` refuses to scaffold a plugin project into an existing path: if the destination exists on disk it bails immediately, mirroring `cargo new` behavior (crates/swc_cli_impl/src/commands/plugin.rs). This prevents overwriting user data with the template.

Solutions

  1. Choose a different destination path or plugin name
  2. Or remove/move the existing directory, then re-run
  3. For partial scaffolds, clear the leftover directory first

Example fix

# before
swc plugin new my-plugin   # ./my-plugin exists
# after
rm -rf ./my-plugin && swc plugin new my-plugin   # or: swc plugin new my-plugin-v2
Defensive patterns

Strategy: validation

Validate before calling

// JavaScript - guard scaffold destination before running the command
import fs from 'node:fs';
if (fs.existsSync(dest)) {
  throw new Error(`destination already exists: ${dest}`);
}
// then: spawn `swc plugin new ${dest}`

Prevention

When it happens

Trigger: Running `swc plugin new my-plugin` when ./my-plugin already exists (file or directory); re-running a scaffold after a partial failure.

Common situations: Retrying after an interrupted scaffold left the directory behind; name collisions with existing packages; scripting scaffold commands without existence checks.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/9e87d45df9a41a69. Report an issue: GitHub.

Appendix: source

Thrown at crates/swc_cli_impl/src/commands/plugin.rs:116

    let mut f = OpenOptions::new()
        .append(true)
        .create(true)
        .open(&ignore_file_path)?;

    write!(f, "{ignore}").context("failed to write to .gitignore file")?;

    Ok(())
}

impl super::CommandRunner for PluginScaffoldOptions {
    /// Create a rust project for the plugin from template.
    /// This largely mimic https://github.com/rust-lang/cargo/blob/master/src/cargo/ops/cargo_new.rs,
    /// but also thinner implementation based on some assumptions like skipping
    /// to support non-git based vcs.
    fn execute(&self) -> Result<()> {
        let path = &self.path;
        if path.exists() {
            anyhow::bail!("destination `{}` already exists", path.display())
        }

        let name = get_name(self)?;

        // Choose to rely on system's git binary instead of depends on git lib for now
        // to avoid bring in large / heavy dependencies into cli binaries.
        // Depends on our usecase grows, we can revisit this.
        let mut base_git_cmd = if cfg!(target_os = "windows") {
            let mut c = std::process::Command::new("cmd");
            c.arg("/C").arg("git");
            c
        } else {
            std::process::Command::new("git")
        };

        // init git repo
        base_git_cmd
            .args(["init", name])

View on GitHub (pinned to 5176682b65)