clockworklabs/SpacetimeDB · error · Error
invalid private initialization record
Error message
invalid private initialization record
What it means
The standalone control DB stores per-database initialization (private environment) metadata as opaque bytes; decode() validates them (size <= 1024, decodeable shape, replica ID consistency with the Database row). Any mismatch yields this single Error::Other sentinel via invalid(), used by decode and every caller (current_generation, initial_environment, upsert_database_with_environment, delete_database_and_environment).
Solutions
- Recreate the database record: delete and re-publish the database so fresh initialization metadata is written.
- Restore a consistent control_db backup that matches the current metadata format.
- If upgrading from an early ENV build, run the proper migration rather than hand-editing the stored bytes.
Example fix
// before: hand-crafted metadata bytes
let bytes = serde_json::to_vec(&json!({"generation": 3, "env": {...}}))?; // >1024B / wrong shape
// after: write through the supported API
control_db.upsert_database_with_environment(&database, &environment, None)?; Defensive patterns
Strategy: validation
Validate before calling
// validate metadata bytes before use
fn valid(bytes: &[u8]) -> bool { bytes.len() <= 1024 && serde_json::from_slice::<InitializationMetadata>(bytes).is_ok() } Type guard
fn is_valid_meta(bytes: &[u8]) -> bool { bytes.len() <= 1024 && serde_json::from_slice::<InitializationMetadata>(bytes).is_ok() } Try / catch
match InitializationMetadata::decode(&bytes, &db) { Err(_) => recreate_database_record(), Ok(m) => use(m) } Prevention
- Never hand-edit control_db metadata blobs
- Use supported APIs to write environment metadata
- Back up and restore control_db atomically
When it happens
Trigger: Reading initialization metadata whose bytes exceed 1024 bytes, fail to deserialize into InitializationMetadata, or whose replica_id disagrees with the Database record; e.g. after a manual DB edit or a failed/aborted migration.
Common situations: Upgrading an older ENV development build that did not record replica_id (now tolerated via serde default, but other shape changes are not); corrupting control_db storage manually; restoring a backup partially.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- Cannot read environment schema: HTTP
- `cmake` not found in PATH.
- Database environment variables can only be changed by…
- Delete for non-existent row when replaying transaction
- dotnet not found in PATH. Please install .NET SDK 8.0 or…
AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-09-20).
Data as JSON: /api/errors/1a3b7369205214f8.
Report an issue: GitHub.
Appendix: source
Thrown at crates/standalone/src/control_db/environment.rs:42
// Keep the existing tree name for on-disk compatibility.
const METADATA_TREE: &str = "database_bootstrap";
const VALUES_TREE: &str = "initial_environment";
#[derive(serde::Serialize, serde::Deserialize)]
#[serde(deny_unknown_fields)]
struct InitializationMetadata {
version: u8,
database_id: u64,
identity: Identity,
program: Hash,
generation: u64,
// Earlier ENV development builds did not record the replica ID.
#[serde(default)]
replica_id: Option<u64>,
}
fn invalid() -> Error {
Error::Other(anyhow::anyhow!("invalid private initialization record"))
}
impl InitializationMetadata {
fn decode(bytes: &[u8], database: &Database) -> Result<Self> {
if bytes.len() > 1024 {
return Err(invalid());
}
let value: Self = serde_json::from_slice(bytes).map_err(|_| invalid())?;
if value.version != 1
|| value.database_id != database.id
|| value.identity != database.database_identity
|| value.generation == 0
{
return Err(invalid());
}
Ok(value)
}
View on GitHub (pinned to eddf9f5014)