unicity-aos/capsule-identity · warning
Failed to parse during auto-detect
Error message
Failed to parse {SPARK_CONFIG_PATH} during auto-detect: {e} What it means
This is a warning logged during automatic identity detection in build_prompt_text_with_spark_loader when the spark.toml config file at SPARK_CONFIG_PATH exists but cannot be parsed as valid TOML (toml::from_str returned Err). The loader treats the failure as non-fatal: it logs the parse error and continues without loading the saved identity, so the user goes through onboarding again. The error message interpolates the underlying TOML parse error `e` describing the exact syntax or type problem.
Solutions
- Open the file at SPARK_CONFIG_PATH and fix the TOML syntax error reported in the message (line/column are included in `e`).
- Verify each field matches SparkConfig's expected types (e.g. callsign must be a string) and that unknown/renamed fields are removed or allowed.
- Regenerate the config by letting the app run onboarding again (delete the corrupt file; it will be re-created on identity save).
- If you control writes to spark.toml, serialize with toml::to_string from SparkConfig instead of hand-writing the file, and validate after writing.
Example fix
# before (spark.toml with broken syntax) [callsign] name = "Nova" # after (valid for SparkConfig) callsign = "Nova"
Defensive patterns
Strategy: validation
Validate before calling
// Before relying on auto-detect, pre-validate the config file.
let raw = std::fs::read_to_string(SPARK_CONFIG_PATH).ok()?;
match toml::from_str::<SparkConfig>(&raw) {
Ok(cfg) if !cfg.callsign.is_empty() => Some(cfg),
_ => None, // fall back to onboarding instead of a silent skip
} Type guard
fn is_valid_spark_config(raw: &str) -> bool {
toml::from_str::<SparkConfig>(raw)
.map(|c| !c.callsign.is_empty())
.unwrap_or(false)
} Try / catch
// Rust has no try/catch; handle the Result explicitly
match toml::from_str::<SparkConfig>(&content) {
Ok(config) if !config.callsign.is_empty() => { /* use config */ }
Ok(_) => { /* empty callsign: stub, run onboarding */ }
Err(e) => log::warn(format!("Bad spark.toml: {e}; running onboarding")),
} Prevention
- Always generate spark.toml via toml::to_string(SparkConfig) rather than hand-editing.
- After writing the config, round-trip parse it once to verify validity.
- Validate the config at app startup and surface the parse error to the user, not just a log.
- Keep SparkConfig serde fields #[serde(default)] where possible so minor schema drift doesn't hard-fail.
When it happens
Trigger: Calling build_prompt_text (directly or via the prompt-building paths) when a spark.toml file exists at SPARK_CONFIG_PATH but toml::from_str fails on its contents — e.g. malformed TOML syntax, a field with the wrong type (callsign defined as a non-string), or a schema/type mismatch against SparkConfig's serde definitions.
Common situations: A user hand-edited spark.toml and introduced a syntax error (missing quote, bad section header); a config file written by an older/newer version with fields whose types changed; the file was corrupted or truncated on disk; a tools-generated config wrote invalid TOML.
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
AI-assisted analysis of unicity-aos/capsule-identity@1364a437f3 (2026-09-13).
Data as JSON: /api/errors/f2e7bb9e0acc335b.
Report an issue: GitHub.
Appendix: source
Thrown at src/lib.rs:189
);
// Auto-detect an existing spark.toml when KV state says not yet onboarded.
// This makes the capsule resilient to KV resets: if the file exists and
// parses successfully we treat the user as onboarded without requiring
// an explicit `identity-import`.
if !self.onboarded
&& let Some(content) = load_spark()
{
// Parse directly instead of going through parse_spark_toml (which
// falls back to a default with a non-empty callsign on error).
match toml::from_str::<SparkConfig>(&content) {
Ok(config) if !config.callsign.is_empty() => {
self.spark = config;
self.onboarded = true;
}
Ok(_) => {} // Empty callsign — treat as stub, don't onboard.
Err(e) => {
log::warn(format!(
"Failed to parse {SPARK_CONFIG_PATH} during auto-detect: {e}"
));
}
}
}
if self.onboarded {
// Prepend the established identity preamble.
let opening = self.spark.build_preamble();
prompt = format!("{opening}\n\n{prompt}");
} else {
// No preamble — don't anchor the model to a name before onboarding.
prompt.push_str("\n\n");
prompt.push_str(ONBOARDING_PROMPT);
}
prompt
}View on GitHub (pinned to 1364a437f3)