nikivdev/code · error

Template path is not a directory: {}

Error message

Template path is not a directory: {}

What it means

Thrown by new_from_template (src/code.rs:107) when the resolved template path exists under ~/new/ but is a file (or other non-directory) rather than a directory. Templates are expected to be directory trees that get copied, so a plain file at that path is invalid.

Source

Thrown at src/code.rs:107

pub fn new_from_template(opts: NewOpts) -> Result<()> {
    let template_root = config::expand_path(DEFAULT_TEMPLATE_ROOT);

    // Get template name (fuzzy select if not provided)
    let template_name = match opts.template {
        Some(t) => t,
        None => match fuzzy_select_template()? {
            Some(t) => t,
            None => return Ok(()), // User cancelled
        },
    };

    let template_dir = template_root.join(template_name.trim());

    if !template_dir.exists() {
        bail!("Template not found: {}", template_dir.display());
    }
    if !template_dir.is_dir() {
        bail!(
            "Template path is not a directory: {}",
            template_dir.display()
        );
    }

    // Resolve target path:
    // - No path: ./<template_name>
    // - Starts with ./ or ../: relative to cwd
    // - Starts with ~ or /: absolute path
    // - Otherwise: relative to ~/code/
    let target = match opts.path {
        None => std::env::current_dir()?.join(&template_name),
        Some(p) => {
            let trimmed = p.trim();
            if trimmed.starts_with("./")
                || trimmed.starts_with("../")
                || trimmed.starts_with('/')
                || trimmed.starts_with('~')

View on GitHub (pinned to a747e741ae)

Solutions

  1. Inspect the path from the error (`ls -la ~/new/<name>`) and remove/replace the non-directory entry.
  2. Extract the template archive into a real directory: `mkdir -p ~/new/<name> && tar -xzf <file> -C ~/new/<name>`.
  3. Fix or remove a broken symlink so the target is a directory.
  4. If it's a stray file, move it out of ~/new/ to keep the template root clean.

Example fix

// before
$ ls -la ~/new/rust-cli   # -rw-r--r-- rust-cli (a zip file)
$ f new rust-cli proj
Error: Template path is not a directory: /home/user/new/rust-cli
// after
$ cd ~/new && mkdir rust-cli && unzip rust-cli.zip -d rust-cli/
$ f new rust-cli proj
Defensive patterns

Strategy: validation

Validate before calling

// Shell: require the template entry to be a real directory
TPL="$HOME/new/$TEMPLATE_NAME"
[ -d "$TPL" ] && [ ! -L "$TPL" -o -d "$TPL/" ] || { echo "not a directory: $TPL"; exit 1; }

Type guard

fn is_valid_template(name: &str) -> bool {
    let p = config::expand_path("~/new").join(name.trim());
    p.is_dir() // is_dir() is false for plain files and broken symlinks
}

Try / catch

match new_from_template(opts) {
    Err(e) if e.to_string().contains("not a directory") => {
        eprintln!("Extract the template archive into ~/new/<name>/ and retry.");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Running `f new <name> ...` where ~/new/<name> exists as a regular file — e.g. a stray file or symlink-to-file was left in the template root, or the template was replaced by a tarball/archive without extracting.

Common situations: Dropping a downloaded zip into ~/new/ and trying to use it directly; a leftover notes file with the same name as a former template; a broken symlink pointing to a file.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/390f7469b8e42672. Report an issue: GitHub.