espanso/espanso · error

unable to parse search configuration

Error message

unable to parse search configuration

What it means

When the `--json` flag is present, search_main parses the input data with serde_json::from_str into a config::SearchConfig; a parse/type mismatch panics via this .expect(). It means the JSON input is not syntactically valid JSON or does not match the expected SearchConfig schema (e.g. missing or wrongly-typed fields like `items`).

Source

Thrown at espanso/src/cli/modulo/search.rs:43

pub fn search_main(matches: &ArgMatches, icon_paths: &IconPaths) -> i32 {
    let as_json: bool = matches.is_present("json");

    let input_file = matches
        .value_of("input_file")
        .expect("missing input, please specify the -i option");
    let data = if input_file == "-" {
        use std::io::Read;
        let mut buffer = String::new();
        std::io::stdin()
            .read_to_string(&mut buffer)
            .expect("unable to obtain input from stdin");
        buffer
    } else {
        std::fs::read_to_string(input_file).expect("unable to read input file")
    };

    let mut config: config::SearchConfig = if as_json {
        serde_json::from_str(&data).expect("unable to parse search configuration")
    } else {
        serde_norway::from_str(&data).expect("unable to parse search configuration")
    };

    // Overwrite the icon
    config.icon = icon_paths
        .logo
        .as_deref()
        .map(|path| path.to_string_lossy().to_string());

    let algorithm = algorithm::get_algorithm(&config.algorithm, true);

    let search = generator::generate(config);
    let result = show(search, algorithm);
    let mut result_map = HashMap::new();
    result_map.insert("selected", result);

    let output = serde_json::to_string(&result_map).expect("unable to encode values as JSON");

View on GitHub (pinned to e6c3736675)

Solutions

  1. Validate the JSON file with a linter (e.g. `jq . input.json`) to catch syntax errors
  2. Compare the input structure against config::SearchConfig fields (items, hint, etc.) and fix types/required fields
  3. Do not pass --json when the input is YAML; use the default YAML path instead
  4. If generating JSON programmatically, print/inspect the payload before handing it to modulo search

Example fix

// before
{"items": [{"id": 1, "label": "x",}}  // trailing comma
// after
{"items": [{"id": "1", "label": "x"}]}
Defensive patterns

Strategy: validation

Validate before calling

jq -e . input.json > /dev/null || { echo 'invalid JSON' >&2; exit 2; }
jq -e 'has("items") and (.items | type == "array")' input.json
espanso modulo search -i input.json --json

Type guard

fn is_valid_search_json(s: &str) -> bool {
    serde_json::from_str::<serde_json::Value>(s)
        .ok()
        .map(|v| v.get("items").map_or(false, |i| i.is_array()))
        .unwrap_or(false)
}

Try / catch

let config = match serde_json::from_str::<config::SearchConfig>(&data) {
    Ok(c) => c,
    Err(e) => { eprintln!("unable to parse search configuration: {e}"); return 1; }
};

Prevention

When it happens

Trigger: Running `espanso modulo search -i <file> --json` where the file contains malformed JSON, or valid JSON whose structure does not deserialize into config::SearchConfig.

Common situations: Hand-editing the JSON input and breaking syntax (trailing commas, unquoted keys); producing the file from a tool that emits a different JSON shape than SearchConfig expects; feeding a YAML file to --json by mistake.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of espanso/espanso@e6c3736675 (2026-09-06). Data as JSON: /api/errors/c631ffc75864b1f2. Report an issue: GitHub.