tonhowtf/omniget · error

tabela de precos invalida

Error message

tabela de precos invalida

What it means

search() loads the price table (from cache or network) and requires the top-level JSON to be an object keyed by model name. If the parsed value is not a JSON object (array, string, null, etc.), it throws "tabela de precos invalida". This is a schema guard protecting the token-matching logic that iterates over object keys.

Solutions

  1. Delete the cached pricing file at cache_path so load() re-fetches a fresh table
  2. Validate the JSON structure of the cache file (top-level must be an object of model keys)
  3. Update the app if the upstream price-table format changed
  4. Add a shape check in load() before caching responses

Example fix

// before: trusting any parseable JSON
if let Ok(text) = tokio::fs::read_to_string(&path).await {
    if let Ok(v) = serde_json::from_str(&text) { return Ok(v); }
}
// after: validate shape before returning
if let Ok(text) = tokio::fs::read_to_string(&path).await {
    if let Ok(v) = serde_json::from_str::<serde_json::Value>(&text) {
        if v.as_object().map(|o| !o.is_empty()).unwrap_or(false) { return Ok(v); }
    }
}
Defensive patterns

Strategy: type-guard

Validate before calling

// inspect the cache before use
let v: serde_json::Value = serde_json::from_str(
    &std::fs::read_to_string(&cache_path)?
)?;
if !v.is_object() {
    std::fs::remove_file(&cache_path)?; // força re-fetch
}

Type guard

fn is_price_table(v: &serde_json::Value) -> bool {
    v.as_object().map(|o| !o.is_empty()).unwrap_or(false)
}

Try / catch

match pricing::search(q, "", 10).await {
    Err(e) if e.to_string().contains("invalida") => {
        // limpar cache e tentar uma vez
        std::fs::remove_file(cache_path()).ok();
        pricing::search(q, "", 10).await
    }
    other => other,
}

Prevention

When it happens

Trigger: The cached pricing.json contains valid JSON of the wrong shape (e.g. truncated into an array, an HTML error page saved as the cache, or an upstream format change), and load() successfully parsed it without shape-checking.

Common situations: Cache file corrupted or half-written by a crash, upstream changed the response schema, a proxy returned an error page that was cached as JSON text (if it happened to parse).

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 tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/78822a08fe643476. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/pricing.rs:133

        .and_then(|p| std::fs::metadata(p).ok())
        .and_then(|m| m.modified().ok())
        .map(|t| chrono::DateTime::<chrono::Utc>::from(t).to_rfc3339());
    Ok(PricingInfo {
        models: v
            .as_object()
            .map(|o| o.len().saturating_sub(1))
            .unwrap_or(0),
        updated_at: updated,
        path: path.map(|p| p.to_string_lossy().to_string()),
    })
}

/// Busca por substring nas chaves; todas as palavras precisam bater.
pub async fn search(query: &str, mode: &str, limit: usize) -> anyhow::Result<Vec<ModelPrice>> {
    let v = load(false).await?;
    let obj = v
        .as_object()
        .ok_or_else(|| anyhow!("tabela de precos invalida"))?;
    let tokens: Vec<String> = query
        .to_lowercase()
        .split_whitespace()
        .map(|s| s.to_string())
        .collect();
    let mut out: Vec<ModelPrice> = obj
        .iter()
        .filter(|(k, _)| *k != "sample_spec")
        .filter(|(k, val)| {
            let hay = format!(
                "{} {}",
                k.to_lowercase(),
                val["litellm_provider"]
                    .as_str()
                    .unwrap_or("")
                    .to_lowercase()
            );
            tokens.iter().all(|t| hay.contains(t))

View on GitHub (pinned to 8600b91f42)