{"record":{"id":"fafe65518229fe13","repo":"clockworklabs/SpacetimeDB","slug":"fatal-error-path-exists-but-is-not-a-directory","errorCode":null,"errorMessage":"Fatal Error: path {} exists but is not a directory.","messagePattern":"Fatal Error: path (.+?) exists but is not a directory\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/cli/src/subcommands/build.rs","lineNumber":83,"sourceCode":"    let build_debug = args.get_flag(\"debug\");\n    let features = features.cloned();\n    let dotnet_version = args.get_one::<u8>(\"dotnet_version\").copied();\n\n    run_build(module_path, lint_dir, build_debug, features, false, dotnet_version)\n}\n\npub fn run_build(\n    module_path: PathBuf,\n    lint_dir: Option<PathBuf>,\n    build_debug: bool,\n    features: Option<OsString>,\n    native_aot: bool,\n    dotnet_version: Option<u8>,\n) -> Result<(PathBuf, &'static str), anyhow::Error> {\n    // Create the project path, or make sure the target project path is empty.\n    if module_path.exists() {\n        if !module_path.is_dir() {\n            return Err(anyhow::anyhow!(\n                \"Fatal Error: path {} exists but is not a directory.\",\n                module_path.display()\n            ));\n        }\n    } else {\n        return Err(anyhow::anyhow!(\n            \"Fatal Error: path {} does not exist.\",\n            module_path.display()\n        ));\n    }\n\n    let result = crate::tasks::build(\n        &module_path,\n        lint_dir.as_deref(),\n        build_debug,\n        features.as_ref(),\n        native_aot,\n        dotnet_version,","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/cli/src/subcommands/build.rs#L65-L101","documentation":"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.","triggerScenarios":"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.","commonSituations":"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`).","solutions":["Point --module-path at the directory that contains the manifest, not the manifest file","Check for path typos: `file <path>` / `ls -la <path>` to see whether it is a file","Fix dangling symlinks that resolve to files"],"exampleFix":"# before\nspacetime build --module-path ./spacetimedb/Cargo.toml\n\n# after\nspacetime build --module-path ./spacetimedb","handlingStrategy":"validation","validationCode":"# Reject file paths before handing them to the build\n[ -d \"$MODULE_PATH\" ] || { echo \"$MODULE_PATH is not a directory\" >&2; exit 1; }\nspacetime build --module-path \"$MODULE_PATH\"","typeGuard":"fn ensure_module_dir(p: &Path) -> anyhow::Result<&Path> {\n    if p.is_dir() { Ok(p) } else { anyhow::bail!(\"module path must be a directory: {}\", p.display()) }\n}","tryCatchPattern":"match run_build(module_path, lint_dir, debug, features, aot, ver).await {\n    Ok(v) => v,\n    Err(e) if e.to_string().contains(\"exists but is not a directory\") => {\n        Err(e.context(\"pass the directory containing the manifest, not the manifest file\"))\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Convention: --module-path always points at a folder, never at Cargo.toml or a .csproj","Validate user-supplied paths with `[ -d ]` in wrappers before invoking the CLI"],"tags":["spacetimedb","cli","build","filesystem","path"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}