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

  1. Recreate the database record: delete and re-publish the database so fresh initialization metadata is written.
  2. Restore a consistent control_db backup that matches the current metadata format.
  3. 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

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


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)