nikivdev/code · error

Relative path cannot be empty.

Error message

Relative path cannot be empty.

What it means

normalize_relative_path sanitizes a user-supplied relative subdirectory name before it is joined onto a project root (used by new_project and migrate_project). After trimming whitespace, an empty string has no meaningful directory component, so the function bails rather than silently resolving to the root itself. This prevents accidentally creating/migrating into the root when an argument was forgotten.

Source

Thrown at src/code.rs:804

        }
    }
    if opts.dry_run {
        println!("Dry run only; no files were changed.");
    }

    Ok(())
}

fn normalize_path(path: &str) -> Result<PathBuf> {
    let expanded = config::expand_path(path);
    let canonical = expanded.canonicalize().unwrap_or(expanded);
    Ok(canonical)
}

fn normalize_relative_path(path: &str) -> Result<PathBuf> {
    let trimmed = path.trim();
    if trimmed.is_empty() {
        bail!("Relative path cannot be empty.");
    }
    let rel = PathBuf::from(trimmed);
    if rel.is_absolute() {
        bail!("Relative path must not be absolute.");
    }
    for component in rel.components() {
        if matches!(component, std::path::Component::ParentDir) {
            bail!("Relative path must not contain '..'.");
        }
    }
    Ok(rel)
}

fn move_dir(from: &Path, to: &Path) -> Result<()> {
    match fs::rename(from, to) {
        Ok(()) => Ok(()),
        Err(err) => {
            if is_cross_device(&err) {

View on GitHub (pinned to a747e741ae)

Solutions

  1. Pass a non-empty relative directory name, e.g. `"my-project"`.
  2. Validate the argument in your shell: `[ -n "$NAME" ] || { echo 'path required'; exit 1; }`.
  3. Check that the value is not only whitespace — trim it before calling if your input may contain spaces.
  4. If the project should live at the root, don't call with an empty path; use the root-targeting API/flag explicitly if one exists.

Example fix

// before
let rel = std::env::var("PROJECT_SUBDIR").unwrap_or_default(); // "" when unset
// after
let rel = std::env::var("PROJECT_SUBDIR").context("PROJECT_SUBDIR must be set")?;
Defensive patterns

Strategy: validation

Validate before calling

let rel = input.trim();
if rel.is_empty() {
    return Err("a non-empty relative project path is required".into());
}

Type guard

fn is_non_empty(s: &str) -> bool { !s.trim().is_empty() }

Try / catch

match new_project(&rel) {
    Err(e) if e.to_string().contains("Relative path cannot be empty") => {
        eprintln!("Provide a project name/path argument.");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling new_project or migrate_project with a relative-path argument that is empty or only whitespace ("", " ", "\t") — e.g. an unset shell variable or an empty CLI flag value.

Common situations: `--path "$NAME"` where $NAME is unset/empty; forms or config files with a blank field; scripts stripping a prefix down to an empty string; users pressing Enter at an interactive prompt.

Related errors


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