clockworklabs/SpacetimeDB · error · anyhow::Error

Module bindings path {} exists but is not a directory.

Error message

Module bindings path {} exists but is not a directory.

What it means

`spacetime dev` validates the module bindings output location: it will create the directory if missing, but if the path exists AND is a regular file (or symlink to one) it bails, because generating bindings requires a directory. The message interpolates the user-supplied relative `--module-bindings-path`.

Source

Thrown at crates/cli/src/subcommands/dev.rs:583

                .and_then(|v| v.as_str())
        });
        if let Some(db_name) = db_to_persist
            && let Some(path) = create_local_spacetime_config_if_missing(&project_dir, db_name)?
        {
            println!("{} Created {}", "✓".green(), strip_verbatim_prefix(&path).display());
        }
    }

    if !module_bindings_dir.exists() {
        // Create the module bindings directory if it doesn't exist
        std::fs::create_dir_all(&module_bindings_dir).with_context(|| {
            format!(
                "Failed to create module bindings path {}",
                module_bindings_dir.display()
            )
        })?;
    } else if !module_bindings_dir.is_dir() {
        anyhow::bail!(
            "Module bindings path {} exists but is not a directory.",
            module_bindings_path.display()
        );
    }

    // Check if we need to login to maincloud
    // Either because --server maincloud was provided, or because any of the publish configs use maincloud
    let needs_maincloud_login = resolved_server == "maincloud"
        || spacetime_config
            .map(|c| {
                c.iter_all_targets().any(|target| {
                    target
                        .additional_fields
                        .get("server")
                        .and_then(|v| v.as_str())
                        .map(|s| s == "maincloud")
                        .unwrap_or(false)
                })

View on GitHub (pinned to 524b4487d9)

Solutions

  1. Inspect the path: `ls -la <project>/<bindings-path>` — if it is a file, decide whether to keep it
  2. Rename or delete the conflicting file, then re-run `spacetime dev` (it will create the directory)
  3. Choose a different directory name for bindings: `--module-bindings-path some/other/dir`

Example fix

# before: ./generated exists as a file
spacetime dev --module-bindings-path generated
# after
rm ./generated && spacetime dev --module-bindings-path generated
Defensive patterns

Strategy: type-guard

Validate before calling

# Ensure the bindings path is absent or a directory
BP=generated
if [ -e "$BP" ] && [ ! -d "$BP" ]; then echo "$BP is a file"; exit 1; fi

Type guard

use std::path::Path;
fn is_usable_bindings_dir(p: &Path) -> bool {
    !p.exists() || p.is_dir()
}

Prevention

When it happens

Trigger: `--module-bindings-path` (or the config equivalent) resolves to an existing file, e.g. a stray `generated` file, a placeholder, or a path where a previous tool wrote a file of the same name.

Common situations: A file created at the intended directory path (touch/echo redirected wrongly); residue from other generators; case-sensitivity or trailing-slash confusion in the path; Windows path quirks.

Related errors


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