Kuberwastaken/claurst · error

source settings.json must be a JSON object

Error message

source settings.json must be a JSON object

What it means

Thrown by `map_settings_preview` (part of `prepare_import_with_paths`) when the source settings.json parsed as a serde_json Value but is not a JSON object. The import path requires the top-level source document to be an object so its fields can be iterated for the preview; arrays, strings, numbers, or null are rejected with this message.

Solutions

  1. Inspect the source file: ensure its top level is `{ ... }`, not an array or scalar.
  2. If it is a wrapped export, unwrap to the inner object before importing.
  3. Re-export settings from the source tool so settings.json is a proper object.
  4. In callers, validate `value.is_object()` before invoking the import/preview APIs.

Example fix

// before
let v: Value = serde_json::from_str(&raw)?;
prepare_import_with_paths(&v, ...)?; // v = [ ... ] -> error

// after
let v: Value = serde_json::from_str(&raw)?;
if !v.is_object() {
    anyhow::bail!("settings source is not an object");
}
prepare_import_with_paths(&v, ...)?;
Defensive patterns

Strategy: type-guard

Validate before calling

let v: serde_json::Value = serde_json::from_str(&raw)?;
if !v.is_object() {
    anyhow::bail!("settings source is not a JSON object");
}

Type guard

fn is_json_object(v: &serde_json::Value) -> bool { v.is_object() }

Try / catch

match prepare_import_with_paths(&source, ...) {
    Ok(preview) => apply(preview),
    Err(e) if e.to_string().contains("must be a JSON object") => {
        // inspect/repair the source file, then retry
        inspect_and_fix_source(path)?;
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Pointing the import command at a settings.json whose top level is an array, string, number, boolean, or null — e.g. a file containing `[...]`, a JSON-lines dump, or a wrongly exported settings file.

Common situations: Importing a file that is actually a JSON array of settings snapshots; importing an export log or wrapped payload like {"settings": {...}} saved incorrectly as `["{...}"]`; a corrupted/partially-written settings file; grabbing the wrong file (not settings.json) that still parses as JSON.

Related errors


AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10). Data as JSON: /api/errors/b131595599a91d85. Report an issue: GitHub.

Appendix: source

Thrown at src-rust/crates/core/src/import_config.rs:307

struct SettingsPreviewOutcome {
    preview_fields: Vec<PreviewField>,
    imported_fields: Vec<String>,
    skipped_fields: Vec<String>,
    imported_count: usize,
    replaced_count: usize,
    kept_count: usize,
    skipped_count: usize,
}

fn map_settings_preview(
    source: &Value,
    current: &Value,
    target: &mut Settings,
) -> Result<SettingsPreviewOutcome> {
    let source_obj = source
        .as_object()
        .ok_or_else(|| anyhow!("source settings.json must be a JSON object"))?;

    let mut preview_fields = Vec::new();
    let mut imported_fields = Vec::new();
    let mut skipped_fields = Vec::new();
    let mut imported_count = 0;
    let mut replaced_count = 0;
    let mut kept_count = 0;
    let mut skipped_count = 0;

    if source_obj.contains_key("model") {
        preview_fields.push(PreviewField {
            name: "model".to_string(),
            action: PreviewAction::Skip,
            reason: Some("model is not imported to keep the current session and default model unchanged".to_string()),
        });
        skipped_fields.push("model".to_string());
        skipped_count += 1;
    } else {

View on GitHub (pinned to b0637c97ec)