{"record":{"id":"c631ffc75864b1f2","repo":"espanso/espanso","slug":"unable-to-parse-search-configuration","errorCode":null,"errorMessage":"unable to parse search configuration","messagePattern":"unable to parse search configuration","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"espanso/src/cli/modulo/search.rs","lineNumber":43,"sourceCode":"pub fn search_main(matches: &ArgMatches, icon_paths: &IconPaths) -> i32 {\n    let as_json: bool = matches.is_present(\"json\");\n\n    let input_file = matches\n        .value_of(\"input_file\")\n        .expect(\"missing input, please specify the -i option\");\n    let data = if input_file == \"-\" {\n        use std::io::Read;\n        let mut buffer = String::new();\n        std::io::stdin()\n            .read_to_string(&mut buffer)\n            .expect(\"unable to obtain input from stdin\");\n        buffer\n    } else {\n        std::fs::read_to_string(input_file).expect(\"unable to read input file\")\n    };\n\n    let mut config: config::SearchConfig = if as_json {\n        serde_json::from_str(&data).expect(\"unable to parse search configuration\")\n    } else {\n        serde_norway::from_str(&data).expect(\"unable to parse search configuration\")\n    };\n\n    // Overwrite the icon\n    config.icon = icon_paths\n        .logo\n        .as_deref()\n        .map(|path| path.to_string_lossy().to_string());\n\n    let algorithm = algorithm::get_algorithm(&config.algorithm, true);\n\n    let search = generator::generate(config);\n    let result = show(search, algorithm);\n    let mut result_map = HashMap::new();\n    result_map.insert(\"selected\", result);\n\n    let output = serde_json::to_string(&result_map).expect(\"unable to encode values as JSON\");","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/espanso/espanso/blob/e6c3736675048026a057f1c4803d59242482fa7b/espanso/src/cli/modulo/search.rs#L25-L61","documentation":"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`).","triggerScenarios":"Running `espanso modulo search -i <file> --json` where the file contains malformed JSON, or valid JSON whose structure does not deserialize into config::SearchConfig.","commonSituations":"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.","solutions":["Validate the JSON file with a linter (e.g. `jq . input.json`) to catch syntax errors","Compare the input structure against config::SearchConfig fields (items, hint, etc.) and fix types/required fields","Do not pass --json when the input is YAML; use the default YAML path instead","If generating JSON programmatically, print/inspect the payload before handing it to modulo search"],"exampleFix":"// before\n{\"items\": [{\"id\": 1, \"label\": \"x\",}}  // trailing comma\n// after\n{\"items\": [{\"id\": \"1\", \"label\": \"x\"}]}","handlingStrategy":"validation","validationCode":"jq -e . input.json > /dev/null || { echo 'invalid JSON' >&2; exit 2; }\njq -e 'has(\"items\") and (.items | type == \"array\")' input.json\nespanso modulo search -i input.json --json","typeGuard":"fn is_valid_search_json(s: &str) -> bool {\n    serde_json::from_str::<serde_json::Value>(s)\n        .ok()\n        .map(|v| v.get(\"items\").map_or(false, |i| i.is_array()))\n        .unwrap_or(false)\n}","tryCatchPattern":"let config = match serde_json::from_str::<config::SearchConfig>(&data) {\n    Ok(c) => c,\n    Err(e) => { eprintln!(\"unable to parse search configuration: {e}\"); return 1; }\n};","preventionTips":["Run the JSON through jq or a linter before passing --json","Keep item objects aligned with config::SearchConfig fields (id, label)","Never feed YAML/other formats with --json set"],"tags":["rust","cli","json","serde","parsing"],"backgroundTag":"schema-validation-failed","analyzedSha":"e6c3736675048026a057f1c4803d59242482fa7b","analyzedAt":"2026-09-06T15:16:34.240Z","contentChangedAt":"2026-09-06T15:16:34.240Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}