chenhg5/cc-connect · error

openai tts: create request: %w

Error message

openai tts: create request: %w

What it means

This error is returned by the OpenAI-compatible TTS Synthesize method when http.NewRequestWithContext fails to construct the POST request to the /audio/speech endpoint. In practice this almost always means the composed URL failed url.Parse validation. The library wraps the underlying error so callers can distinguish request-construction failures from network and API failures.

Source

Thrown at core/tts.go:250

		voice = "alloy"
	}
	reqBody := map[string]any{
		"model": o.Model,
		"input": text,
		"voice": voice,
	}
	if opts.Speed > 0 {
		reqBody["speed"] = opts.Speed
	}
	jsonData, err := json.Marshal(reqBody)
	if err != nil {
		return nil, "", fmt.Errorf("openai tts: marshal request: %w", err)
	}

	url := strings.TrimRight(o.BaseURL, "/") + "/audio/speech"
	req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(jsonData))
	if err != nil {
		return nil, "", fmt.Errorf("openai tts: create request: %w", err)
	}
	req.Header.Set("Authorization", "Bearer "+o.APIKey)
	req.Header.Set("Content-Type", "application/json")

	resp, err := o.Client.Do(req)
	if err != nil {
		return nil, "", fmt.Errorf("openai tts: request: %w", err)
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		return nil, "", fmt.Errorf("openai tts API %d: %s", resp.StatusCode, body)
	}

	mp3Data, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, "", fmt.Errorf("openai tts: read audio: %w", err)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Check the configured BaseURL: it must be a clean absolute URL like https://api.openai.com/v1 with no spaces or stray characters
  2. Trim whitespace/newlines from the BaseURL when loading config
  3. If the cause is context.Canceled/DeadlineExceeded, create the context fresh for each Synthesize call instead of reusing a canceled one

Example fix

// before
BaseURL: "https://api.openai.com/v1 " // trailing space breaks url parse
// after
BaseURL: strings.TrimSpace("https://api.openai.com/v1")
Defensive patterns

Strategy: validation

Validate before calling

if u, err := url.Parse(strings.TrimSpace(cfg.TTSBaseURL)); err != nil || u.Scheme == "" || u.Host == "" {
    return fmt.Errorf("invalid tts base_url %q: %w", cfg.TTSBaseURL, err)
}

Type guard

func validBaseURL(s string) bool {
    u, err := url.Parse(strings.TrimSpace(s))
    return err == nil && (u.Scheme == "https" || u.Scheme == "http") && u.Host != ""
}

Try / catch

mp3, format, err := tts.Synthesize(ctx, text)
if err != nil {
    if strings.Contains(err.Error(), "create request") {
        // configuration problem: check BaseURL
    }
    return err
}

Prevention

When it happens

Trigger: o.BaseURL contains characters that make the concatenated URL unparseable (spaces, control characters, unencoded specials), or the context ctx passed to Synthesize is already canceled at request-construction time.

Common situations: A misconfigured base_url in config.toml with a stray space or newline, an empty/garbage BaseURL value, or passing an already-expired/canceled context into Synthesize.

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 chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/b80f12a0bd59cfc8. Report an issue: GitHub.