clockworklabs/SpacetimeDB · error
Environment key : config input must be a string, boolean or…
Error message
Environment key {name:?}: config input must be a string, boolean or JSON number What it means
When publishing, environment values sourced from the spacetimedb config file must be JSON strings, booleans, or numbers. Other JSON types (arrays, objects, null) cannot be coerced to an environment string value, so `resolve` bails with this message naming the offending key.
Solutions
- Change the config value for the named key to a string, boolean, or number.
- Quote structured values as strings if the literal text is intended (e.g. `MY_KEY: "[1,2]"`).
- Remove null placeholders from the environment section.
Example fix
// before (config)
MY_KEY: {nested: true}
// after (config)
MY_KEY: "nested=true" Defensive patterns
Strategy: validation
Validate before calling
fn valid_env_value(v: &serde_json::Value) -> bool { matches!(v, serde_json::Value::String(_) | serde_json::Value::Bool(_) | serde_json::Value::Number(_)) } Type guard
fn is_scalar_json(v: &serde_json::Value) -> bool { !matches!(v, serde_json::Value::Object(_) | serde_json::Value::Array(_) | serde_json::Value::Null) } Try / catch
match result { Err(e) if e.to_string().contains("config input must be") => { /* fix config value type for named key */ }, Err(e) => return Err(e), Ok(v) => v } Prevention
- Keep env config values scalar: strings, booleans, numbers only.
- Quote any value that should be taken literally, especially bracketed or structured text.
- Lint the env section for nulls and nested structures before publishing.
When it happens
Trigger: A config file's environment section contains a key whose value is an object, array, or null (e.g. `MY_KEY: {a: 1}` or `MY_KEY: null`) during `spacetime publish`.
Common situations: Copy-pasting structured config into the env section; forgetting to quote a value that YAML/JSON5 parses as an object or list; accidentally leaving `null` placeholders.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- database is a required field in publish config
- Environment key is both supplied and removed
- Environment key : numeric config input must use JSON number…
- Environment ' ' cannot use an enum payload
- Environment ' ' must be a string or simple enum
AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-09-20).
Data as JSON: /api/errors/adebbe70a301819c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/subcommands/publish/environment.rs:57
pub(super) fn resolve(
schema: &EnvironmentSchema,
config: Option<&Value>,
mut shell: impl FnMut(&str) -> Option<OsString>,
) -> anyhow::Result<Resolved> {
let mut resolved = Resolved {
values: BTreeMap::new(),
sources: BTreeMap::new(),
};
if let Some(config) = config {
let config = config.as_object().context("Environment config must be an object")?;
for (name, value) in config {
spacetimedb_lib::environment::validate_key(name)?;
let value = match value {
Value::String(value) => value.clone(),
Value::Bool(value) => value.to_string(),
Value::Number(value) => value.to_string(),
_ => anyhow::bail!("Environment key {name:?}: config input must be a string, boolean or JSON number"),
};
resolved.values.insert(name.clone(), value);
resolved.sources.insert(name.clone(), Source::Config);
}
}
// Lookup only the new artifact's declared names, never enumerate ambient values.
for declaration in schema.declarations() {
if let Some(value) = shell(&declaration.name) {
let value = value
.into_string()
.map_err(|_| anyhow::anyhow!("Environment key {:?}: shell input must be UTF-8", declaration.name))?;
resolved.values.insert(declaration.name.clone(), value);
resolved.sources.insert(declaration.name.clone(), Source::Shell);
}
}
schema.validate_supplied_values(&resolved.values)?;
Ok(resolved)
}View on GitHub (pinned to eddf9f5014)