clockworklabs/SpacetimeDB · error

unknown field

Error message

unknown field `{field}`

What it means

When the SpacetimeConfig deserializer reports an unknown field, `decode_config` re-raises it as `unknown field \`{field}\`` — but only if the field name is a safe, bounded, ordinary identifier (non-empty, ≤64 chars, alphanumeric/underscore/dash). This gives actionable misspelling feedback without exposing secret values.

Solutions

  1. Correct the field name to one supported by your CLI version (`spacetime --help` or docs).
  2. Remove obsolete fields no longer recognized by the current CLI.
  3. Check for typos — the error names the exact offending field.

Example fix

// before (config)
envrionment: { KEY: "v" }
// after (config)
environment: { KEY: "v" }
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN = ['environment','database','server','project'];
for (const key of Object.keys(topLevelConfig)) if (!KNOWN.includes(key)) console.warn('unknown config field:', key);

Type guard

fn is_known_config_field(key: &str, known: &[&str]) -> bool { known.contains(&key) }

Try / catch

match result { Err(e) if e.to_string().starts_with("unknown field") => { let f = /* parse field from message */; eprintln!("Fix or remove config key: {f}"); }, Err(e) => return Err(e), Ok(v) => v }

Prevention

When it happens

Trigger: A typo'd or unsupported key in the spacetimedb config file, e.g. `envrionment:` instead of `environment:`, provided the key passes the safe-name filter.

Common situations: Misspelling top-level config keys; using keys from an older/newer CLI version that no longer exist; copying config examples from outdated docs.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-09-20). Data as JSON: /api/errors/805b8ca9cb02ebd3. Report an issue: GitHub.

Appendix: source

Thrown at crates/cli/src/spacetime_config/environment.rs:113

/// receive visit_u128 from Value's deserializer. That buffer cannot represent
/// u128, while the arbitrary-precision JSON parser preserves its decimal token.
/// Diagnostics discard values while retaining a bounded, ordinary unknown field
/// name, which is useful for correcting misspelled configuration options.
pub(super) fn decode_config(value: Value) -> anyhow::Result<super::SpacetimeConfig> {
    let encoded = serde_json::to_vec(&value).map_err(|_| anyhow::anyhow!("Invalid configuration structure"))?;
    serde_json::from_slice(&encoded).map_err(|error| {
        let diagnostic = error.to_string();
        if let Some((field, suffix)) = diagnostic
            .strip_prefix("unknown field `")
            .and_then(|message| message.split_once('`'))
            && suffix.starts_with(", expected ")
            && !field.is_empty()
            && field.len() <= 64
            && field
                .bytes()
                .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'_' | b'-'))
        {
            return anyhow::anyhow!("unknown field `{field}`");
        }
        anyhow::anyhow!("Invalid configuration structure")
    })
}

fn is_space(ch: char) -> bool {
    ch.is_whitespace() || ch == '\u{feff}'
}

fn restore(value: &mut Value, prefix: &str, numbers: &[&str], env_key: Option<&str>) -> anyhow::Result<()> {
    match value {
        Value::String(s) => {
            if let Some(index) = s.strip_prefix(prefix).and_then(|s| s.parse::<usize>().ok()) {
                let token = numbers[index];
                *value = if let Some(env_key) = env_key {
                    Value::Number(token.parse().map_err(|_| {
                        anyhow::anyhow!(
                            "Environment key {:?}: numeric config input must use JSON number syntax",

View on GitHub (pinned to eddf9f5014)