{"record":{"id":"128e527d2f6fb811","repo":"tonhowtf/omniget","slug":"tabela-de-precos-http","errorCode":null,"errorMessage":"tabela de precos: HTTP {}","messagePattern":"tabela de precos: HTTP (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/pricing.rs","lineNumber":78,"sourceCode":"    match client.get(LITELLM_URL).send().await {\n        Ok(resp) if resp.status().is_success() => {\n            let text = resp.text().await?;\n            let v: serde_json::Value = serde_json::from_str(&text)?;\n            if let Some(parent) = path.parent() {\n                std::fs::create_dir_all(parent)?;\n            }\n            tokio::fs::write(&path, &text).await?;\n            Ok(v)\n        }\n        other => {\n            // Sem rede: usa o que tiver em disco, mesmo velho.\n            if let Ok(text) = tokio::fs::read_to_string(&path).await {\n                if let Ok(v) = serde_json::from_str(&text) {\n                    return Ok(v);\n                }\n            }\n            match other {\n                Ok(r) => Err(anyhow!(\"tabela de precos: HTTP {}\", r.status())),\n                Err(e) => Err(anyhow!(\"tabela de precos indisponivel: {}\", e)),\n            }\n        }\n    }\n}\n\nfn per_m(v: &serde_json::Value, key: &str) -> Option<f64> {\n    v.get(key).and_then(|x| x.as_f64()).map(|x| x * 1_000_000.0)\n}\n\nfn to_price(key: &str, v: &serde_json::Value) -> ModelPrice {\n    ModelPrice {\n        key: key.to_string(),\n        provider: v[\"litellm_provider\"].as_str().unwrap_or(\"\").to_string(),\n        mode: v[\"mode\"].as_str().unwrap_or(\"\").to_string(),\n        input_per_m: per_m(v, \"input_cost_per_token\"),\n        output_per_m: per_m(v, \"output_cost_per_token\"),\n        cache_read_per_m: per_m(v, \"cache_read_input_token_cost\"),","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/pricing.rs#L60-L96","documentation":"When the cached price table is stale or unreadable, load() fetches it from the remote pricing source; if the HTTP response comes back but with a non-success status, it is wrapped as \"tabela de precos: HTTP <status>\". This distinguishes a reachable server returning an error code from a connection-level failure (which yields the 'indisponivel' variant instead).","triggerScenarios":"load(force) or a stale-cache load where the pricing HTTP endpoint returns 4xx/5xx — endpoint moved, rate-limited (429), server error (500/503), or blocked by a proxy/gateway (403).","commonSituations":"Upstream pricing API deprecated its URL, temporary upstream outage, rate limiting after frequent refreshes, corporate proxy rejecting the request.","solutions":["Check the reported HTTP status: 429 means wait/backoff and retry; 5xx means retry later","Verify the pricing endpoint URL hasn't changed (update the app if the upstream API moved)","Force a refresh later (call with force=true) once the service recovers","Check proxy/firewall rules if the status is 403"],"exampleFix":"// retry with backoff on 5xx/429\nmatch other {\n    Ok(r) if r.status().is_server_error() || r.status().as_u16() == 429 =>\n        Err(anyhow!(\"tabela de precos: HTTP {} (retry later)\", r.status())),\n    Ok(r) => Err(anyhow!(\"tabela de precos: HTTP {}\", r.status())),\n    Err(e) => Err(anyhow!(\"tabela de precos indisponivel: {}\", e)),\n}","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match pricing::info().await {\n    Err(e) if e.to_string().contains(\"tabela de precos: HTTP\") => {\n        tokio::time::sleep(Duration::from_secs(30)).await;\n        retry_with_backoff(3).await?; // 429/5xx são transientes\n    }\n    other => other?,\n}","preventionTips":["Cache the table aggressively and only force-refresh on demand","Apply backoff on 429/5xx before surfacing the error","Monitor the upstream endpoint so you notice URL/API changes early"],"tags":["http","network","pricing","rust"],"backgroundTag":"http-error-response","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}