Billionmail/BillionMail · error
cartesia clone API call: %w
Error message
cartesia clone API call: %w
What it means
CloneVoice executes the prepared Cartesia clone request via cfg.doHTTP and wraps client-side transport failures with 'cartesia clone API call: %w'. This error fires before any HTTP status check — it means the request never completed, not that the API returned an error payload (non-200 responses produce the separate 'cartesia clone API error %d' error).
Source
Thrown at core/internal/service/video_gen/voice.go:150
// CloneVoice creates a cloned voice from an audio sample URL via Cartesia API.
func CloneVoice(ctx context.Context, cfg VoiceConfig, name, audioURL string) (*VoiceCloneResponse, error) {
req := VoiceCloneRequest{
Name: name,
Description: fmt.Sprintf("Cloned voice for %s", name),
Mode: "url",
AudioURL: audioURL,
Language: "en",
}
httpReq, err := BuildCloneRequest(cfg, req)
if err != nil {
return nil, err
}
httpReq = httpReq.WithContext(ctx)
resp, err := cfg.doHTTP(httpReq)
if err != nil {
return nil, fmt.Errorf("cartesia clone API call: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("cartesia clone API error %d: %s", resp.StatusCode, string(body))
}
var result VoiceCloneResponse
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, fmt.Errorf("decode clone response: %w", err)
}
return &result, nil
}
// TextToSpeech generates audio from text using a Cartesia voice.
// Returns the path to the output WAV file.
func TextToSpeech(ctx context.Context, cfg VoiceConfig, voiceID, transcript, filename string) (string, error) {View on GitHub (pinned to fc36c76c05)
Solutions
- Unwrap with errors.As(err, &urlErr) and check errors.Is(err, context.DeadlineExceeded)/context.Canceled to classify timeout vs shutdown vs network
- Verify outbound connectivity to the Cartesia host (curl https://api.cartesia.ai from the same container)
- Increase the context timeout for large voice sample uploads, and check the base URL scheme/host
- Retry once with backoff for transient network errors before failing the pipeline
- Confirm the API key is valid only if the request completes with a non-200 status (different error path)
Example fix
// before
resp, err := cfg.doHTTP(httpReq)
if err != nil {
return nil, fmt.Errorf("cartesia clone API call: %w", err)
}
// after
resp, err := cfg.doHTTP(httpReq)
if err != nil {
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
return nil, fmt.Errorf("cartesia clone call cancelled or timed out: %w", err)
}
var urlErr *url.Error
if errors.As(err, &urlErr) && isTransient(urlErr) {
resp, err = retryWithBackoff(httpReq)
if err != nil {
return nil, fmt.Errorf("cartesia clone API call after retry: %w", err)
}
return resp, nil
}
return nil, fmt.Errorf("cartesia clone API call: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
if ctx.Err() != nil {
return fmt.Errorf("clone aborted before call: %w", ctx.Err())
}
if netErr := checkConnectivity("https://api.cartesia.ai"); netErr != nil {
return fmt.Errorf("cartesia unreachable: %w", netErr)
} Try / catch
clone, err := video_gen.CloneVoice(ctx, cfg, req)
if err != nil {
var urlErr *url.Error
switch {
case errors.Is(err, context.Canceled):
// caller cancelled; no retry
case errors.Is(err, context.DeadlineExceeded):
// increase timeout or shrink sample payload, then retry
case errors.As(err, &urlErr) && isTransientNetError(urlErr):
// retry with exponential backoff
default:
return fmt.Errorf("voice clone failed: %w", err)
}
} Prevention
- Give voice-clone calls a context timeout sized for sample upload time
- Distinguish context.Canceled/DeadlineExceeded from network errors via errors.Is before retrying
- Monitor egress/DNS health in the deployment environment
- Retry only transient *url.Error causes (connection refused/reset, timeouts), never after cancellation
When it happens
Trigger: cfg.doHTTP(httpReq) returns a *url.Error: DNS resolution failure, connection refused/timeout, TLS handshake failure, or the request context (attached via httpReq.WithContext(ctx)) was cancelled before a response arrived.
Common situations: No outbound internet or blocked egress to api.cartesia.ai; DNS outage; expired/invalid API key is NOT this error (that returns non-200 and hits the status branch); pipeline shutdown or per-call timeout cancelling ctx mid-request.
Related errors
- cartesia TTS API call: %w
- base URL not configured
- base URL accessibility test failed: %w
- resolve failed
- Failed to get server IP: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/f2a256787422539c.
Report an issue: GitHub.