clockworklabs/SpacetimeDB · error · anyhow::Error
database is a required field in publish config
Error message
database is a required field in publish config
What it means
While preparing dev mode, the CLI maps every publish config to its `database` field in order to stream logs and pick a database for the client process (`db_names_for_logging[0]`). If any entry in `publish_configs` lacks a `database` string, the `.ok_or_else` fires and the whole `collect::<Result<..>>` aborts. Note it indexes `[0]` right after, so an empty publish list would panic rather than error here.
Source
Thrown at crates/cli/src/subcommands/dev.rs:668
if sc.dev.as_ref().and_then(|d| d.run.as_ref()).is_none() {
detect_and_save_client_command(&project_dir, Some(sc.clone()))
} else {
sc.dev.as_ref().and_then(|d| d.run.clone())
}
} else {
// No config file - try to detect and create new
detect_and_save_client_command(&project_dir, None)
};
// Extract database names from publish configs for log streaming
let db_names_for_logging: Vec<String> = publish_configs
.iter()
.map(|config| {
config
.get_config_value("database")
.and_then(|v| v.as_str())
.ok_or_else(|| anyhow::anyhow!("database is a required field in publish config"))
.map(|s| s.to_string())
})
.collect::<Result<Vec<_>, _>>()?;
// Use first database for client process
let db_name_for_client = &db_names_for_logging[0];
// Extract watch directories from publish configs
let watch_dirs = extract_watch_dirs(&publish_configs, &spacetimedb_dir, &project_dir);
println!("\n{}", "Starting development mode...".green().bold());
if db_names_for_logging.len() == 1 {
println!("Database: {}", db_names_for_logging[0].cyan());
} else {
println!("Databases: {}", db_names_for_logging.join(", ").cyan());
}
// Announce watch directoriesView on GitHub (pinned to 524b4487d9)
Solutions
- Add `"database": "<name>"` to every publish target in `spacetime.json`
- Validate the file: `spacetime json`-lint or `cat spacetime.json | jq .publish` to inspect each target
- Ensure the value is a JSON string, not a number or nested object
Example fix
// before
"publish": [{ "module_path": "./spacetimedb" }]
// after
"publish": [{ "module_path": "./spacetimedb", "database": "mydb" }] Defensive patterns
Strategy: validation
Validate before calling
# Assert every publish target names a database before dev
jq -e '.publish | length > 0 and all(.[]; (.database // "") != "")' spacetime.json \
|| { echo 'publish targets missing "database"'; exit 1; } Type guard
// In Rust, if building configs programmatically:
fn has_database(t: &serde_json::Value) -> bool {
t.get("database").and_then(|v| v.as_str()).map_or(false, |s| !s.is_empty())
} Prevention
- Treat `database` as mandatory in every publish target
- Lint spacetime.json in CI with jq or a JSON-schema check
When it happens
Trigger: A `spacetime.json` publish target missing the `database` key, or having it as a non-string JSON value (number, object).
Common situations: Hand-editing spacetime.json and forgetting `database`; migrating schema where the field was renamed; copy-pasting a partial target from docs; using `${DB}`-style placeholders that never got substituted.
Related errors
- No such saved server configuration: {server} Add a new serve
- No default server configuration. Set an existing server as t
- Server nickname {} already in use: {}://{}
- Server host name is ambiguous with existing server nickname:
- Server not specified and no default server configured.
AI-assisted analysis of clockworklabs/SpacetimeDB@524b4487d9 (2026-08-16).
Data as JSON: /api/errors/6bdedb515e60b27a.
Report an issue: GitHub.