Billionmail/BillionMail · error

create clone request: %w

Error message

create clone request: %w

What it means

After marshaling the body, BuildCloneRequest calls http.NewRequest("POST", cfg.voiceBaseURL()+cartesiaClonePath, ...); an invalid URL or method makes NewRequest return a *url.Error which is wrapped as 'create clone request: %w'. This indicates the Cartesia base URL configured in VoiceConfig is malformed.

Source

Thrown at core/internal/service/video_gen/voice.go:104

func DefaultTTSOutputFormat() TTSOutputFormat {
	return TTSOutputFormat{
		Container:  "wav",
		SampleRate: 44100,
		Encoding:   "pcm_f32le",
	}
}

// BuildCloneRequest constructs the HTTP request for voice cloning.
// Exported for testing without making API calls.
func BuildCloneRequest(cfg VoiceConfig, req VoiceCloneRequest) (*http.Request, error) {
	body, err := json.Marshal(req)
	if err != nil {
		return nil, fmt.Errorf("marshal clone request: %w", err)
	}

	httpReq, err := http.NewRequest("POST", cfg.voiceBaseURL()+cartesiaClonePath, bytes.NewReader(body))
	if err != nil {
		return nil, fmt.Errorf("create clone request: %w", err)
	}

	httpReq.Header.Set("X-API-Key", cfg.APIKey)
	httpReq.Header.Set("Cartesia-Version", cartesiaAPIVersion)
	httpReq.Header.Set("Content-Type", "application/json")
	return httpReq, nil
}

// BuildTTSRequest constructs the HTTP request for text-to-speech.
// Exported for testing without making API calls.
func BuildTTSRequest(cfg VoiceConfig, req TTSRequest) (*http.Request, error) {
	body, err := json.Marshal(req)
	if err != nil {
		return nil, fmt.Errorf("marshal TTS request: %w", err)
	}

	httpReq, err := http.NewRequest("POST", cfg.voiceBaseURL()+cartesiaTTSPath, bytes.NewReader(body))
	if err != nil {

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Log/print cfg.voiceBaseURL()+cartesiaClonePath and run url.Parse on it to see the exact parse failure
  2. Set the Cartesia base URL to the correct default (https://api.cartesia.ai) via the VoiceConfig/env var, trimmed of whitespace
  3. TrimSpace and validate with url.Parse (require scheme http/https) when constructing VoiceConfig from environment
  4. Add a startup config check that fails fast on an unparseable voice base URL

Example fix

// before
cfg := VoiceConfig{BaseURL: os.Getenv("CARTESIA_URL")} // "" or "https://api.cartesia.ai\n"
httpReq, err := http.NewRequest("POST", cfg.voiceBaseURL()+cartesiaClonePath, bytes.NewReader(body))
// after
base := strings.TrimSpace(os.Getenv("CARTESIA_URL"))
if base == "" {
    base = "https://api.cartesia.ai"
}
if _, perr := url.Parse(base + cartesiaClonePath); perr != nil {
    return nil, fmt.Errorf("invalid cartesia base URL %q: %w", base, perr)
}
cfg := VoiceConfig{BaseURL: base}
httpReq, err := http.NewRequest("POST", cfg.voiceBaseURL()+cartesiaClonePath, bytes.NewReader(body))
Defensive patterns

Strategy: validation

Validate before calling

func validateVoiceBaseURL(cfg VoiceConfig) error {
    u, err := url.Parse(cfg.voiceBaseURL() + cartesiaClonePath)
    if err != nil || u.Scheme == "" || u.Host == "" {
        return fmt.Errorf("invalid cartesia base URL: %q", cfg.voiceBaseURL())
    }
    return nil
}

Try / catch

httpReq, err := video_gen.BuildCloneRequest(cfg, req)
if err != nil {
    var urlErr *url.Error
    if errors.As(err, &urlErr) {
        log.Errorf("bad clone endpoint URL: %v", urlErr)
    }
    return err
}

Prevention

When it happens

Trigger: http.NewRequest fails because cfg.voiceBaseURL() produces an unparseable URL — empty base URL, control characters, spaces, or a bad scheme — so the POST target cfg.voiceBaseURL()+cartesiaClonePath cannot be parsed (TestBuildCloneRequest_EmptyAPIKey exercises config edge cases; the URL itself is the failure point here).

Common situations: Missing CARTESIA_API_URL-style env var leaving the base URL empty; a base URL set with a trailing newline/space from config parsing; scheme typo like 'htp://'; URL assembled from untrimmed user config.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/ed0de2c15479594b. Report an issue: GitHub.