Billionmail/BillionMail · error
cartesia TTS API call: %w
Error message
cartesia TTS API call: %w
What it means
TextToSpeech posts to Cartesia /tts/bytes via cfg.doHTTP; if the HTTP round trip itself fails — DNS failure, connection refused/timeout, TLS error, or rate-limited client rejection — the error is wrapped as 'cartesia TTS API call'. This is a transport-level failure before any status code is available.
Source
Thrown at core/internal/service/video_gen/voice.go:189
}
req := TTSRequest{
VoiceID: voiceID,
Transcript: transcript,
ModelID: "sonic-2",
OutputFormat: DefaultTTSOutputFormat(),
Language: "en",
}
httpReq, err := BuildTTSRequest(cfg, req)
if err != nil {
return "", err
}
httpReq = httpReq.WithContext(ctx)
resp, err := cfg.doHTTP(httpReq)
if err != nil {
return "", fmt.Errorf("cartesia TTS API call: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return "", fmt.Errorf("cartesia TTS API error %d: %s", resp.StatusCode, string(body))
}
outPath := filepath.Join(cfg.OutputDir, filename)
f, err := os.Create(outPath)
if err != nil {
return "", fmt.Errorf("create output file: %w", err)
}
defer f.Close()
if _, err := io.Copy(f, resp.Body); err != nil {
return "", fmt.Errorf("write audio data: %w", err)
}View on GitHub (pinned to fc36c76c05)
Solutions
- Inspect the wrapped %w chain for the concrete net error (timeout, refused, TLS).
- Confirm outbound HTTPS to api.cartesia.ai works (curl -v https://api.cartesia.ai).
- Check ctx deadlines and the RateLimitedClient budget; increase limits or wait.
- Verify proxy env vars (HTTP_PROXY/HTTPS_PROXY/NO_PROXY) and CA certificates in the container.
- Add retry with backoff for transient timeouts/refusals.
Example fix
// before
resp, err := cfg.doHTTP(httpReq)
if err != nil {
return "", fmt.Errorf("cartesia TTS API call: %w", err)
}
// after
var netErr net.Error
resp, err := cfg.doHTTP(httpReq)
if err != nil {
if errors.As(err, &netErr) && netErr.Timeout() {
return "", retryable(fmt.Errorf("cartesia TTS API call: %w", err))
}
return "", fmt.Errorf("cartesia TTS API call: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
// pre-flight before calling TextToSpeech
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
conn, err := net.DialTimeout("tcp", "api.cartesia.ai:443", 5*time.Second)
if err != nil {
return fmt.Errorf("cartesia unreachable: %w", err)
}
conn.Close() Try / catch
var netErr net.Error
path, err := video_gen.TextToSpeech(ctx, cfg, voiceID, transcript, filename)
if err != nil {
if strings.Contains(err.Error(), "cartesia TTS API call") && errors.As(err, &netErr) && netErr.Timeout() {
// transient: retry with exponential backoff
}
return err
} Prevention
- Configure sane timeouts on the HTTPClient / RateLimitedClient
- Allow egress to api.cartesia.ai:443 in firewalls and security groups
- Set HTTP(S)_PROXY correctly in restricted networks
- Keep CA certificates up to date in container images
When it happens
Trigger: No network/DNS resolution for api.cartesia.ai, connection timeout exceeded, TLS certificate problems, an HTTP proxy blocking egress, or the RateLimitedClient refusing the request when its budget is exhausted.
Common situations: Egress firewall in Docker/K8s blocking outbound 443, expired system CA bundle, missing HTTP_PROXY/HTTPS_PROXY config, ctx already cancelled/expired before the call, rate limiter configured too tightly.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- cartesia clone API call: %w
- base URL not configured
- base URL accessibility test failed: %w
- download file failed:
- rate limiter: %w
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/ff7eeab7a23cb0b4.
Report an issue: GitHub.