lbjlaq/Antigravity-Manager · critical
Failed to parse model_specs.json
Error message
Failed to parse model_specs.json
What it means
The SPECS lazy static embeds resources/model_specs.json at compile time and parses it with expect, panicking at first access if the embedded JSON is invalid. This is a startup-time invariant: the shipped resource must always be parseable.
Solutions
- Validate model_specs.json with serde_json (or a CI lint step) before building — the error is baked in at compile time
- Fix the JSON syntax/type errors in resources/model_specs.json
- Replace expect with a logged error and empty fallback so one bad file doesn't panic the proxy
Example fix
// before
serde_json::from_str(json_str).expect("Failed to parse model_specs.json")
// after
serde_json::from_str(json_str).unwrap_or_else(|e| {
log_error("model_specs.json parse failed: {e}");
Default::default()
}) Defensive patterns
Strategy: validation
Validate before calling
let specs: SpecsConfig = serde_json::from_str(&std::fs::read_to_string("resources/model_specs.json")?)?; // CI check before build Try / catch
match serde_json::from_str::<SpecsConfig>(json_str) { Ok(v) => v, Err(e) => { log::error("model_specs parse: {e}"); Default::default() } } Prevention
- Add a CI job that parses model_specs.json with the same serde types
- Reject files with BOM or trailing garbage
- Keep the JSON machine-generated to avoid hand-edit syntax errors
When it happens
Trigger: First access to SPECS (e.g. resolve_alias) after model_specs.json was edited/committed with invalid JSON, duplicate keys breaking serde expectations, or wrong types for ModelSpec fields.
Common situations: A hand-edit or CI generation step produced malformed JSON; a ModelSpec field type changed making existing JSON invalid; file re-encoded with BOM breaking serde_json.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
- 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 lbjlaq/Antigravity-Manager@90a2b6b207 (2026-09-19).
Data as JSON: /api/errors/52c6ecfd9455a8d2.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/src/proxy/model_specs.rs:21
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelSpec {
pub max_output_tokens: Option<u64>,
pub thinking_budget: Option<u64>,
pub is_thinking: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct SpecsConfig {
models: HashMap<String, ModelSpec>,
aliases: HashMap<String, String>,
}
static SPECS: Lazy<SpecsConfig> = Lazy::new(|| {
let json_str = include_str!("../../resources/model_specs.json");
serde_json::from_str(json_str).expect("Failed to parse model_specs.json")
});
/// 获取归一化后的模型 ID (基于别名)
pub fn resolve_alias(model_id: &str) -> String {
SPECS
.aliases
.get(model_id)
.cloned()
.unwrap_or_else(|| model_id.to_string())
}
/// 获取模型输出 Token 限额 (动态优先)
pub fn get_max_output_tokens(model_id: &str, token: Option<&ProxyToken>) -> u64 {
let std_id = resolve_alias(model_id);
// 1. 尝试从账号动态数据中读取
if let Some(t) = token {
if let Some(&limit) = t.model_limits.get(&std_id) {View on GitHub (pinned to 90a2b6b207)