clockworklabs/SpacetimeDB · error · anyhow::Error

Invalid system variable {s}

Error message

Invalid system variable {s}

What it means

StVarName::from_str is the parser behind system-variable assignment (SET GLOBAL style statements) and accepts exactly one name in this version: "row_limit" (ST_VARNAME_ROW_LIMIT). Any other string — misspelled, wrong casing, or a variable introduced in a newer spacetimedb release — fails to parse with this error.

Source

Thrown at crates/datastore/src/system_tables.rs:1694

    fn from(value: StVarName) -> Self {
        match value {
            StVarName::RowLimit => ST_VARNAME_ROW_LIMIT,
        }
    }
}
impl From<StVarName> for AlgebraicValue {
    fn from(value: StVarName) -> Self {
        let value: &'static str = value.into();
        AlgebraicValue::String(value.into())
    }
}
impl FromStr for StVarName {
    type Err = anyhow::Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            ST_VARNAME_ROW_LIMIT => Ok(StVarName::RowLimit),
            _ => Err(anyhow::anyhow!("Invalid system variable {s}")),
        }
    }
}
impl_st!([] StVarName, AlgebraicType::String);
impl_serialize!([] StVarName, (self, ser) => <&'static str>::from(*self).serialize(ser));
impl<'de> Deserialize<'de> for StVarName {
    fn deserialize<D: spacetimedb_lib::de::Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
        let s = <&str>::deserialize(de)?;
        s.parse().map_err(D::Error::custom)
    }
}

impl StVarName {
    pub fn type_of(&self) -> AlgebraicType {
        match self {
            StVarName::RowLimit => AlgebraicType::U64,
        }
    }

View on GitHub (pinned to 6dee26c6ef)

Solutions

  1. Use the exact name row_limit
  2. Check the spacetimedb docs/changelog for the version's supported system variables
  3. Validate variable names client-side against a whitelist before issuing the statement
  4. Upgrade client and server together if the variable exists only in a newer release

Example fix

-- before
SET GLOBAL rowlimit = 100;

-- after
SET GLOBAL row_limit = 100;
Defensive patterns

Strategy: validation

Validate before calling

fn is_known_system_variable(name: &str) -> bool {
    matches!(name, "row_limit")
}

// before issuing the statement:
assert!(is_known_system_variable(var), "unknown system variable {var}");

Type guard

fn parse_system_variable(s: &str) -> Option<StVarName> {
    match s {
        "row_limit" => Some(StVarName::RowLimit),
        _ => None,
    }
}

Try / catch

Catch the parse error at the statement boundary and return it to the client as an unknown-variable diagnostic listing the supported names for this server version.

Prevention

When it happens

Trigger: Executing SET GLOBAL <name> = ... (or the equivalent API) with a name other than row_limit: "rowlimit", "ROW_LIMIT", "query_timeout", or any variable not supported by this build.

Common situations: SQL scripts ported from other databases assuming familiar variable names; clients targeting a newer spacetimedb than the server; simple typos in migration or tuning scripts.

Related errors


AI-assisted analysis of clockworklabs/SpacetimeDB@6dee26c6ef (2026-08-20). Data as JSON: /api/errors/bde3db1690b557cd. Report an issue: GitHub.