From 668767958c3b141117fa74d152fdcf7030d5125e Mon Sep 17 00:00:00 2001 From: clockwork-labs-bot Date: Wed, 25 Feb 2026 19:03:07 -0500 Subject: [PATCH 1/3] Fix spacetime dev ignoring --module-path and config module-path for file watcher (#4443) Two bugs caused spacetime dev to always watch ./spacetimedb/ regardless of module-path settings: 1. Config's module-path in additional_fields was checked for existence (to skip the recovery prompt) but never used to set spacetimedb_dir. The directory stayed as project_dir/spacetimedb even when config specified a different path. 2. determine_publish_configs() hardcoded "spacetimedb" as the module-path in fallback publish configs. This wrong path propagated to extract_watch_dirs() (file watcher) and the publish loop, overriding any CLI or config value. Fix: resolve spacetimedb_dir from config's module-path when CLI doesn't provide one, and pass the resolved path to determine_publish_configs() for the fallback instead of hardcoding. --- crates/cli/src/subcommands/dev.rs | 60 +++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/crates/cli/src/subcommands/dev.rs b/crates/cli/src/subcommands/dev.rs index 3b1ca604bd7..1324ad5ff2a 100644 --- a/crates/cli/src/subcommands/dev.rs +++ b/crates/cli/src/subcommands/dev.rs @@ -290,6 +290,19 @@ pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::E } } + // If config has a module-path and CLI didn't provide one, resolve spacetimedb_dir from it. + // This handles the case where spacetime.json specifies module-path but has no publish targets. + if module_path_from_cli.is_none() { + if let Some(config_module_path) = loaded_config + .as_ref() + .and_then(|lc| lc.config.additional_fields.get("module-path")) + .and_then(|v| v.as_str()) + { + let p = PathBuf::from(config_module_path); + spacetimedb_dir = if p.is_absolute() { p } else { project_dir.join(p) }; + } + } + let spacetime_config = loaded_config.as_ref().map(|lc| &lc.config); // A config has publish targets if it has a "database" field or children let has_publish_targets_in_config = spacetime_config @@ -365,6 +378,7 @@ pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::E &publish_schema, &publish_args, resolved_server, + &spacetimedb_dir, )?; // Check if we are in a SpacetimeDB project directory, but only if we don't have any @@ -470,6 +484,7 @@ pub async fn exec(mut config: Config, args: &ArgMatches) -> Result<(), anyhow::E &publish_schema, &publish_args, resolved_server, + &spacetimedb_dir, )?; } @@ -846,6 +861,7 @@ fn determine_publish_configs<'a>( publish_schema: &'a CommandSchema, publish_args: &'a ArgMatches, resolved_server: &str, + default_module_path: &Path, ) -> anyhow::Result>> { // Build publish configs. It is easier to work with one type of data, // so if we don't have publish configs from the config file, we build a single @@ -869,7 +885,7 @@ fn determine_publish_configs<'a>( let mut config_map = HashMap::new(); config_map.insert("database".to_string(), json!(db_name)); config_map.insert("server".to_string(), json!(resolved_server)); - config_map.insert("module-path".to_string(), json!("spacetimedb")); + config_map.insert("module-path".to_string(), json!(default_module_path.to_string_lossy())); Ok(vec![CommandConfig::new(publish_schema, config_map, publish_args)?]) } else { @@ -1728,8 +1744,16 @@ mod tests { let publish_schema = publish::build_publish_schema(&publish_cmd).unwrap(); let publish_args = publish_cmd.clone().get_matches_from(vec!["publish"]); - let result = - determine_publish_configs(None, None, &publish_cmd, &publish_schema, &publish_args, "local").unwrap(); + let result = determine_publish_configs( + None, + None, + &publish_cmd, + &publish_schema, + &publish_args, + "local", + Path::new("spacetimedb"), + ) + .unwrap(); assert!(result.is_empty()); } @@ -1748,6 +1772,7 @@ mod tests { &publish_schema, &publish_args, "local", + Path::new("spacetimedb"), ) .unwrap(); @@ -1783,6 +1808,7 @@ mod tests { &publish_schema, &publish_args, "local", + Path::new("spacetimedb"), ) .unwrap(); @@ -1814,6 +1840,7 @@ mod tests { &publish_schema, &publish_args, "local", + Path::new("spacetimedb"), ) .unwrap(); @@ -1825,6 +1852,33 @@ mod tests { ); } + #[test] + fn test_determine_publish_configs_fallback_uses_provided_module_path() { + // When falling through to CLI database, the fallback should use the provided + // default_module_path instead of hardcoding "spacetimedb" + let publish_cmd = publish::cli(); + let publish_schema = publish::build_publish_schema(&publish_cmd).unwrap(); + let publish_args = publish_cmd.clone().get_matches_from(vec!["publish", "my-db"]); + + let custom_path = Path::new("/custom/module/path"); + let result = determine_publish_configs( + Some("my-db".to_string()), + None, + &publish_cmd, + &publish_schema, + &publish_args, + "local", + custom_path, + ) + .unwrap(); + + assert_eq!(result.len(), 1); + assert_eq!( + result[0].get_config_value("module_path").and_then(|v| v.as_str()), + Some("/custom/module/path") + ); + } + #[test] fn test_cli_env_flag_defaults_to_dev() { // Verify that the dev CLI defaults --env to "dev" From ef440b71a8e9349f03b21051e5643a01686c9482 Mon Sep 17 00:00:00 2001 From: clockwork-labs-bot Date: Wed, 25 Feb 2026 19:53:42 -0500 Subject: [PATCH 2/3] Improve error when module directory does not exist (#4443) Instead of the confusing: Could not detect the language of the module. Are you in a SpacetimeDB project directory? Now shows: Module directory does not exist: ''. Check your --module-path flag or the module-path setting in spacetime.json. --- crates/cli/src/util.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/cli/src/util.rs b/crates/cli/src/util.rs index fe08be66e31..ad1f33301ef 100644 --- a/crates/cli/src/util.rs +++ b/crates/cli/src/util.rs @@ -249,6 +249,13 @@ pub fn find_module_path(project_dir: &Path) -> Option { pub fn detect_module_language(path_to_project: &Path) -> anyhow::Result { // TODO: Possible add a config file durlng spacetime init with the language + if !path_to_project.exists() { + anyhow::bail!( + "Module directory does not exist: '{}'. \ + Check your --module-path flag or the module-path setting in spacetime.json.", + path_to_project.display() + ); + } // check for Cargo.toml if path_to_project.join("Cargo.toml").exists() { Ok(ModuleLanguage::Rust) From d40df6cbb71d483e418cb5e44db7265d892ce40a Mon Sep 17 00:00:00 2001 From: clockwork-labs-bot Date: Wed, 25 Feb 2026 19:55:43 -0500 Subject: [PATCH 3/3] Revert "Improve error when module directory does not exist (#4443)" This reverts commit ef440b71a8e9349f03b21051e5643a01686c9482. --- crates/cli/src/util.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/crates/cli/src/util.rs b/crates/cli/src/util.rs index ad1f33301ef..fe08be66e31 100644 --- a/crates/cli/src/util.rs +++ b/crates/cli/src/util.rs @@ -249,13 +249,6 @@ pub fn find_module_path(project_dir: &Path) -> Option { pub fn detect_module_language(path_to_project: &Path) -> anyhow::Result { // TODO: Possible add a config file durlng spacetime init with the language - if !path_to_project.exists() { - anyhow::bail!( - "Module directory does not exist: '{}'. \ - Check your --module-path flag or the module-path setting in spacetime.json.", - path_to_project.display() - ); - } // check for Cargo.toml if path_to_project.join("Cargo.toml").exists() { Ok(ModuleLanguage::Rust)