clockworklabs/SpacetimeDB · error
Invalid JSON5 configuration
Error message
Invalid JSON5 configuration
What it means
After masking numeric literals and strings, the parser re-parses the reconstructed JSON5 text into a JSON Value. If that final parse fails, the config is rejected with this opaque message — deliberately vague because JSON5 parser diagnostics may echo source lines containing secrets.
Solutions
- Validate the config's JSON5 syntax with a linter/JSON5 parser.
- Fix missing commas, braces, or brackets around the edited section.
- Temporarily test with `json5.parse()` locally to locate the line, since the CLI hides diagnostics to protect secrets.
Example fix
// before (config)
{ env: { A: 1 B: 2 } }
// after (config)
{ env: { A: 1, B: 2 } } Defensive patterns
Strategy: validation
Validate before calling
// validate overall JSON5 structure before invoking the CLI
const json5 = require('json5');
json5.parse(fs.readFileSync(configPath, 'utf8')); // throws with line info locally Try / catch
match result { Err(e) if e.to_string() == "Invalid JSON5 configuration" => { eprintln!("Structural syntax error in config; validate with a local JSON5 parser"); }, Err(e) => return Err(e), Ok(v) => v } Prevention
- Lint the config with a JSON5 parser/editor plugin after each edit.
- Fix commas, braces, and brackets before publishing; the CLI hides diagnostics to protect secrets.
- Keep machine-generated configs under syntax tests.
When it happens
Trigger: Structurally invalid JSON5 config: missing commas, unbalanced braces/brackets, trailing garbage, or numeric placeholder corruption after masking.
Common situations: Hand-edited configs with syntax mistakes; comment or comma typos; editors leaving stray characters in spacetimedb config files.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to parse config file
- Invalid JSON5 string
- Environment key : numeric config input must use JSON number…
- Invalid numeric configuration input
- cannot replace without enclosing directory
AI-assisted analysis of clockworklabs/SpacetimeDB@eddf9f5014 (2026-09-20).
Data as JSON: /api/errors/b613f096c9cdd79a.
Report an issue: GitHub.
Appendix: source
Thrown at crates/cli/src/spacetime_config/environment.rs:89
strings.push(json5::from_str(&content[start..i]).map_err(|_| anyhow::anyhow!("Invalid JSON5 string"))?);
}
}
// Check decoded strings as well: Unicode escapes must not manufacture an
// internal marker and cause a string to be interpreted as a number.
let mut prefix = "__spacetime_numeric_".to_owned();
while content.contains(&prefix) || strings.iter().any(|s| s.contains(&prefix)) {
prefix.push('_');
}
let mut text = String::with_capacity(content.len());
let mut previous = 0;
for (index, (start, end)) in replacements.into_iter().enumerate() {
text.push_str(&content[previous..start]);
text.push_str(&format!("\"{prefix}{index}\""));
previous = end;
}
text.push_str(&content[previous..]);
// Parser diagnostics may quote the source line, which can contain secrets.
let mut value: Value = json5::from_str(&text).map_err(|_| anyhow::anyhow!("Invalid JSON5 configuration"))?;
restore(&mut value, &prefix, &numbers, None)?;
Ok(value)
}
/// Deserialize through JSON text so Serde's flattened-field buffer does not
/// 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()View on GitHub (pinned to eddf9f5014)