clockworklabs/SpacetimeDB · error · std::io::Error
Missing "version" field in TypeScript bindings package.json
Error message
Missing "version" field in TypeScript bindings package.json
What it means
Raised by extract_ts_bindings_version in the CLI build script while compiling the `spacetime` CLI. The script reads crates/bindings-typescript/package.json to embed the TypeScript bindings version next to the workspace metadata used by `spacetime init` templates. If the parsed JSON has no top-level version field, or version is not a JSON string, it returns InvalidData with this message and the .expect() at build.rs:109 panics the build.
Source
Thrown at crates/cli/build.rs:491
if let Some(version) = version_opt {
versions.insert(name.clone(), version);
}
}
}
Ok((edition, versions))
}
fn extract_ts_bindings_version(path: &Path) -> io::Result<String> {
let content = fs::read_to_string(path)?;
let parsed: serde_json::Value =
serde_json::from_str(&content).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
parsed
.get("version")
.and_then(serde_json::Value::as_str)
.map(|s| s.to_string())
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidData,
"Missing \"version\" field in TypeScript bindings package.json",
)
})
}
fn normalize_version(version: &str) -> String {
version.trim().trim_start_matches('=').to_string()
}
fn write_if_changed(path: &Path, contents: &[u8]) -> io::Result<()> {
match fs::read(path) {
Ok(existing) if existing == contents => Ok(()),
_ => {
if let Some(parent) = path.parent() {
fs::create_dir_all(parent)?;
}
let mut file = fs::File::create(path)?;View on GitHub (pinned to 6dee26c6ef)
Solutions
- Add a string "version" field to crates/bindings-typescript/package.json, e.g. "version": "1.0.0" consistent with the release.
- Restore the file from git history if it was mangled: `git checkout HEAD -- crates/bindings-typescript/package.json`.
- Fix the release/version-bump script so it always preserves the version field when rewriting package.json.
Example fix
// before (crates/bindings-typescript/package.json)
{
"name": "bindings-typescript"
}
// after
{
"name": "bindings-typescript",
"version": "1.0.0"
} Defensive patterns
Strategy: validation
Validate before calling
let pkg: serde_json::Value =
serde_json::from_str(&std::fs::read_to_string("crates/bindings-typescript/package.json")?)?;
anyhow::ensure!(
pkg.get("version").map(|v| v.is_string()).unwrap_or(false),
"package.json must carry a string \"version\" field"
); Try / catch
match extract_ts_bindings_version(&ts_bindings_package) {
Ok(v) => v,
Err(e) if e.kind() == io::ErrorKind::InvalidData => {
// restore the file from git and rebuild: git checkout HEAD -- crates/bindings-typescript/package.json
return Err(anyhow!("{e}"));
}
Err(e) => return Err(e.into()),
} Prevention
- Validate package.json with a schema check in CI that requires a string version field.
- Make version-bump scripts patch fields in place rather than regenerating the whole file.
- Re-run the CLI build immediately after touching bindings-typescript/package.json to catch stripped fields early.
When it happens
Trigger: Building the SpacetimeDB CLI when crates/bindings-typescript/package.json has had its "version" field removed or set to a non-string (number, object) - e.g. by release automation, a bad merge, or regenerating the file from a partial template.
Common situations: Version-bump scripts that rewrite package.json and drop fields; JSON merge conflicts resolved by hand; vendored copies where the file was regenerated without version.
Related errors
- workspace manifest is not a table
- Invalid version string: ${version}
- Invalid JSON: failed to parse string
- Unknown UUID version
- Injected commit hash is not valid unicode: {gross:?}
AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20).
Data as JSON: /api/errors/c880a6eaa1025a47.
Report an issue: GitHub.