{"record":{"id":"5d81abab0276f379","repo":"zeroclaw-labs/zeroclaw","slug":"telnyx-api-error","errorCode":null,"errorMessage":"Telnyx API error ({}): {}","messagePattern":"Telnyx API error \\((.+?)\\): (.+?)","errorType":"http","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-providers/src/telnyx.rs","lineNumber":206,"sourceCode":"            model: model.to_string(),\n            messages,\n            temperature,\n        };\n\n        let response = self\n            .client\n            .post(self.chat_url())\n            .header(\"Authorization\", format!(\"Bearer {}\", api_key))\n            .header(\"Content-Type\", \"application/json\")\n            .json(&request)\n            .send()\n            .await?;\n\n        if !response.status().is_success() {\n            let status = response.status();\n            let error = response.text().await?;\n            let sanitized = super::sanitize_api_error(&error);\n            anyhow::bail!(\"Telnyx API error ({}): {}\", status, sanitized);\n        }\n\n        let chat_response: ChatResponse = response.json().await?;\n\n        chat_response\n            .choices\n            .into_iter()\n            .next()\n            .map(|c| c.message.content)\n            .ok_or_else(|| {\n                ::zeroclaw_log::record!(\n                    ERROR,\n                    ::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Fail)\n                        .with_outcome(::zeroclaw_log::EventOutcome::Failure),\n                    \"telnyx: empty choices in response\"\n                );\n                anyhow::Error::msg(\"No response from Telnyx\")\n            })","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-providers/src/telnyx.rs#L188-L224","documentation":"chat_with_system sent a chat completion to Telnyx and got a non-success status; the body is passed through sanitize_api_error to strip credentials before being embedded. The status code is included, so 401/400/429/500 each point at a distinct fix.","triggerScenarios":"401 from a bad key; 400 from an unsupported model name or invalid parameters for a single system-prompt turn; 429 rate limiting; 5xx provider errors.","commonSituations":"Key rotated but config still holds the old one; model id not enabled for the account; bursty traffic hitting Telnyx quotas; Telnyx incident.","solutions":["Read the status in the message: 401 → fix the API key; 400 → fix model name/parameters.","429 → back off and retry with exponential delay, or lower request rate.","Confirm the model id in the provider entry is one Telnyx's models endpoint actually lists.","5xx → check Telnyx status page and retry later."],"exampleFix":"# before — model id not offered by Telnyx\n[providers.models.telnyx.main]\nmodel = \"gpt-4o\"\n\n# after — an id that appears in the Telnyx models list\n[providers.models.telnyx.main]\nmodel = \"meta-llama/Llama-3.1-70b-instruct\"","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"Parse the status from the message: retry 429 and 5xx with exponential backoff + jitter (cap ~3 retries); fail immediately on 400/401 — they are deterministic config errors. Log the sanitized body verbatim for diagnosis.","preventionTips":["Keep the Telnyx key in a secret manager with rotation, not stale env files","Use model ids straight from the models listing","Stay under Telnyx rate limits with client-side throttling"],"tags":["telnyx","http-status","llm-provider","chat","network"],"backgroundTag":"llm-api-http-error","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}