{"record":{"id":"6bdedb515e60b27a","repo":"clockworklabs/SpacetimeDB","slug":"database-is-a-required-field-in-publish-config","errorCode":null,"errorMessage":"database is a required field in publish config","messagePattern":"database is a required field in publish config","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/cli/src/subcommands/dev.rs","lineNumber":668,"sourceCode":"\n        if sc.dev.as_ref().and_then(|d| d.run.as_ref()).is_none() {\n            detect_and_save_client_command(&project_dir, Some(sc.clone()))\n        } else {\n            sc.dev.as_ref().and_then(|d| d.run.clone())\n        }\n    } else {\n        // No config file - try to detect and create new\n        detect_and_save_client_command(&project_dir, None)\n    };\n\n    // Extract database names from publish configs for log streaming\n    let db_names_for_logging: Vec<String> = publish_configs\n        .iter()\n        .map(|config| {\n            config\n                .get_config_value(\"database\")\n                .and_then(|v| v.as_str())\n                .ok_or_else(|| anyhow::anyhow!(\"database is a required field in publish config\"))\n                .map(|s| s.to_string())\n        })\n        .collect::<Result<Vec<_>, _>>()?;\n\n    // Use first database for client process\n    let db_name_for_client = &db_names_for_logging[0];\n\n    // Extract watch directories from publish configs\n    let watch_dirs = extract_watch_dirs(&publish_configs, &spacetimedb_dir, &project_dir);\n\n    println!(\"\\n{}\", \"Starting development mode...\".green().bold());\n    if db_names_for_logging.len() == 1 {\n        println!(\"Database: {}\", db_names_for_logging[0].cyan());\n    } else {\n        println!(\"Databases: {}\", db_names_for_logging.join(\", \").cyan());\n    }\n\n    // Announce watch directories","sourceCodeStart":650,"sourceCodeEnd":686,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/cli/src/subcommands/dev.rs#L650-L686","documentation":"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.","triggerScenarios":"A `spacetime.json` publish target missing the `database` key, or having it as a non-string JSON value (number, object).","commonSituations":"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.","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"],"exampleFix":"// before\n\"publish\": [{ \"module_path\": \"./spacetimedb\" }]\n// after\n\"publish\": [{ \"module_path\": \"./spacetimedb\", \"database\": \"mydb\" }]","handlingStrategy":"validation","validationCode":"# Assert every publish target names a database before dev\njq -e '.publish | length > 0 and all(.[]; (.database // \"\") != \"\")' spacetime.json \\\n  || { echo 'publish targets missing \"database\"'; exit 1; }","typeGuard":"// In Rust, if building configs programmatically:\nfn has_database(t: &serde_json::Value) -> bool {\n    t.get(\"database\").and_then(|v| v.as_str()).map_or(false, |s| !s.is_empty())\n}","tryCatchPattern":null,"preventionTips":["Treat `database` as mandatory in every publish target","Lint spacetime.json in CI with jq or a JSON-schema check"],"tags":["cli","configuration","spacetime-json","spacetimedb"],"backgroundTag":"missing-config-field","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}