clockworklabs/SpacetimeDB · error

Fatal Error: path {} exists but is not a directory.

Error message

Fatal Error: path {} exists but is not a directory.

What it means

run_build's precondition: module_path must be an existing directory. In this branch the path exists on disk but is not a directory — a regular file or a symlink to one — so the build would have no directory to work in and the task runner is never invoked. The prefix 'Fatal Error' is conventional for these path guards.

Source

Thrown at crates/cli/src/subcommands/build.rs:83

    let build_debug = args.get_flag("debug");
    let features = features.cloned();
    let dotnet_version = args.get_one::<u8>("dotnet_version").copied();

    run_build(module_path, lint_dir, build_debug, features, false, dotnet_version)
}

pub fn run_build(
    module_path: PathBuf,
    lint_dir: Option<PathBuf>,
    build_debug: bool,
    features: Option<OsString>,
    native_aot: bool,
    dotnet_version: Option<u8>,
) -> Result<(PathBuf, &'static str), anyhow::Error> {
    // Create the project path, or make sure the target project path is empty.
    if module_path.exists() {
        if !module_path.is_dir() {
            return Err(anyhow::anyhow!(
                "Fatal Error: path {} exists but is not a directory.",
                module_path.display()
            ));
        }
    } else {
        return Err(anyhow::anyhow!(
            "Fatal Error: path {} does not exist.",
            module_path.display()
        ));
    }

    let result = crate::tasks::build(
        &module_path,
        lint_dir.as_deref(),
        build_debug,
        features.as_ref(),
        native_aot,
        dotnet_version,

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Point --module-path at the directory that contains the manifest, not the manifest file
  2. Check for path typos: `file <path>` / `ls -la <path>` to see whether it is a file
  3. Fix dangling symlinks that resolve to files

Example fix

# before
spacetime build --module-path ./spacetimedb/Cargo.toml

# after
spacetime build --module-path ./spacetimedb
Defensive patterns

Strategy: validation

Validate before calling

# Reject file paths before handing them to the build
[ -d "$MODULE_PATH" ] || { echo "$MODULE_PATH is not a directory" >&2; exit 1; }
spacetime build --module-path "$MODULE_PATH"

Type guard

fn ensure_module_dir(p: &Path) -> anyhow::Result<&Path> {
    if p.is_dir() { Ok(p) } else { anyhow::bail!("module path must be a directory: {}", p.display()) }
}

Try / catch

match run_build(module_path, lint_dir, debug, features, aot, ver).await {
    Ok(v) => v,
    Err(e) if e.to_string().contains("exists but is not a directory") => {
        Err(e.context("pass the directory containing the manifest, not the manifest file"))
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Passing `spacetime build --module-path <file>` where <file> is e.g. Cargo.toml or the .csproj itself rather than the directory containing it; a symlink resolving to a file.

Common situations: Pointing --module-path at the manifest file instead of the folder; tab-completion picking the file; a path with a trailing component that is a file (e.g. `.../module/Cargo.toml`).

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16). Data as JSON: /api/errors/fafe65518229fe13. Report an issue: GitHub.