clockworklabs/SpacetimeDB · error · std::io::Error
workspace section missing
Error message
workspace section missing
What it means
Same CLI build-script path (crates/cli/build.rs:454): after confirming the root Cargo.toml is a table, extract_workspace_metadata requires a [workspace] section to read workspace.package.edition (defaulting to 2021) and workspace.dependencies versions for the embedded template metadata. A table-rooted manifest without [workspace] produces this InvalidData error, and the .expect() at build.rs:104 panics the build.
Source
Thrown at crates/cli/build.rs:454
repo_root.display()
)
})
}
fn extract_workspace_metadata(path: &Path) -> io::Result<(String, BTreeMap<String, String>)> {
let content = fs::read_to_string(path)?;
let parsed: Value = content
.parse()
.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
let table = parsed
.as_table()
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "workspace manifest is not a table"))?;
let workspace = table
.get("workspace")
.and_then(Value::as_table)
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "workspace section missing"))?;
let edition = workspace
.get("package")
.and_then(Value::as_table)
.and_then(|pkg| pkg.get("edition"))
.and_then(Value::as_str)
.unwrap_or("2021")
.to_string();
let mut versions = BTreeMap::new();
if let Some(deps) = workspace.get("dependencies").and_then(Value::as_table) {
for (name, value) in deps {
let version_opt = match value {
Value::String(s) => Some(normalize_version(s)),
Value::Table(table) => table.get("version").and_then(Value::as_str).map(normalize_version),
_ => None,
};
View on GitHub (pinned to 6dee26c6ef)
Solutions
- Restore a [workspace] section in the root Cargo.toml with the crate members (e.g. [workspace] with members = ["crates/*"]).
- Recover the section from git history: `git show HEAD:Cargo.toml`.
- If the workspace root genuinely moved, restore the expected repo layout so crates/cli/build.rs finds the original root manifest.
Example fix
# before (root Cargo.toml) [package] name = "root" version = "0.1.0" # after [workspace] members = ["crates/*"]
Defensive patterns
Strategy: validation
Validate before calling
let parsed: toml::Value = std::fs::read_to_string("Cargo.toml")?.parse()?;
anyhow::ensure!(
parsed.get("workspace").map(|w| w.is_table()).unwrap_or(false),
"root Cargo.toml is missing its [workspace] section"
); Try / catch
match extract_workspace_metadata(&workspace_cargo) {
Ok(meta) => meta,
Err(e) if e.kind() == io::ErrorKind::InvalidData && e.to_string().contains("workspace section") => {
// restore [workspace] from git history, then rebuild
return Err(anyhow!("{e}"));
}
Err(e) => return Err(e.into()),
} Prevention
- Run `cargo metadata --no-deps` in CI - it fails fast when [workspace] is missing.
- Keep dependency bots and merge tooling from deleting manifest sections they do not recognize.
- After restructuring a fork, confirm crates/cli/build.rs still finds a root workspace manifest at the repo root.
When it happens
Trigger: Building the `spacetime` CLI when the root Cargo.toml is valid table-rooted TOML but contains no [workspace] section - e.g. the root was converted to a plain package manifest, or [workspace] was dropped in a merge.
Common situations: Forks that restructure the repo (moving the workspace elsewhere) without leaving a root workspace manifest; automated dependency bots deleting sections they do not understand; a crate manifest copy-pasted over the root.
Related errors
- workspace manifest is not a table
- failed to read {} bytes of commit payload: {}
- failed to read checksum: {e}
- cannot serialize refs without a typespace
- Cannot extract accessor name from query
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/9f7bc1075af233fe.
Report an issue: GitHub.