{"record":{"id":"167fb943cd7e9cfa","repo":"clockworklabs/SpacetimeDB","slug":"workspace-manifest-is-not-a-table","errorCode":null,"errorMessage":"workspace manifest is not a table","messagePattern":"workspace manifest is not a table","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"error","filePath":"crates/cli/build.rs","lineNumber":449,"sourceCode":"    // We happen to know our own directory structure, so we can just walk the tree to get to the root.\n    let repo_root = manifest_dir.join(\"..\").join(\"..\");\n    repo_root.canonicalize().unwrap_or_else(|err| {\n        panic!(\n            \"Failed to canonicalize repo_root path {}: {err:#?}\",\n            repo_root.display()\n        )\n    })\n}\n\nfn extract_workspace_metadata(path: &Path) -> io::Result<(String, BTreeMap<String, String>)> {\n    let content = fs::read_to_string(path)?;\n    let parsed: Value = content\n        .parse()\n        .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;\n\n    let table = parsed\n        .as_table()\n        .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, \"workspace manifest is not a table\"))?;\n\n    let workspace = table\n        .get(\"workspace\")\n        .and_then(Value::as_table)\n        .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, \"workspace section missing\"))?;\n\n    let edition = workspace\n        .get(\"package\")\n        .and_then(Value::as_table)\n        .and_then(|pkg| pkg.get(\"edition\"))\n        .and_then(Value::as_str)\n        .unwrap_or(\"2021\")\n        .to_string();\n\n    let mut versions = BTreeMap::new();\n    if let Some(deps) = workspace.get(\"dependencies\").and_then(Value::as_table) {\n        for (name, value) in deps {\n            let version_opt = match value {","sourceCodeStart":431,"sourceCodeEnd":467,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/6dee26c6efc2856793e12b148a59742964f5d783/crates/cli/build.rs#L431-L467","documentation":"Runtime error in the spacetimedb CLI's build script (crates/cli/build.rs). While compiling the CLI, the script parses the repository-root Cargo.toml to embed the workspace edition and dependency versions into generated template code (so `spacetime init` can rewrite template manifests without hardcoded versions). After TOML parsing succeeds, it requires the document root to be a table; anything else (an array, a bare value, a mangled file) yields io::ErrorKind::InvalidData with this message, which the .expect() at build.rs:104 turns into a build-script panic.","triggerScenarios":"Running cargo build on the SpacetimeDB workspace (anything that compiles the `spacetime` CLI crate) when the root Cargo.toml parses as TOML but its root node is not a table - e.g. the file was truncated, replaced by a non-manifest TOML document, or re-serialized into an array/scalar by tooling.","commonSituations":"Codegen or scripts that rewrite the root manifest and emit a non-table document; badly resolved merge conflicts leaving the top level malformed; forks whose tooling writes the wrong file to the root path.","solutions":["Open the repository-root Cargo.toml and restore a normal manifest shape: top-level keys plus [workspace], [workspace.package] and [workspace.dependencies] sections.","If a generator rewrote the file, fix the generator to round-trip a table-rooted TOML document and regenerate.","Smoke-test with `cargo metadata --no-deps` in the repo root; if cargo itself rejects the file, fix the manifest before rebuilding the CLI."],"exampleFix":"# before (root Cargo.toml root is not a table)\n[\n  { name = \"my-workspace\" }\n]\n\n# after\n[workspace]\nmembers = [\"crates/*\"]","handlingStrategy":"validation","validationCode":"// Rust: validate the workspace manifest before building the CLI crate\nlet content = std::fs::read_to_string(\"Cargo.toml\")?;\nlet parsed: toml::Value = content.parse()?; // fails on invalid TOML\nanyhow::ensure!(parsed.is_table(), \"root Cargo.toml must be a TOML table\");","typeGuard":null,"tryCatchPattern":"match extract_workspace_metadata(&workspace_cargo) {\n    Ok(meta) => meta,\n    Err(e) if e.kind() == io::ErrorKind::InvalidData => {\n        // regenerate/restore the root manifest, then fail the build with a clear message\n        return Err(anyhow!(\"root Cargo.toml malformed: {e}\"));\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Never rewrite the workspace-root manifest with tools that re-serialize the whole document - patch fields in place.","Add `cargo metadata --no-deps` to CI as a manifest smoke test before building the CLI crate.","Review root Cargo.toml changes as carefully as lockfile changes; many crates derive versions from it."],"tags":["rust","cargo","toml","build-script","spacetimedb-cli"],"backgroundTag":"invalid-cargo-manifest","analyzedSha":"6dee26c6efc2856793e12b148a59742964f5d783","analyzedAt":"2026-08-20T06:08:37.179Z","contentChangedAt":"2026-08-20T06:08:37.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}