sipeed/picoclaw · error

failed to create request: %w

Error message

failed to create request: %w

What it means

Thrown when http.NewRequestWithContext cannot construct the POST request to t.apiBase + "/v1/speech-to-text" in ElevenLabsTranscriber.Transcribe. The method and body are always valid, so the failure is a malformed URL: url.Parse rejects control characters, spaces, or a missing/invalid scheme/host. The error wraps *url.Error with Op 'parse'.

Source

Thrown at pkg/audio/asr/elevenlabs_transcriber.go:95

	if _, err = io.Copy(part, audioFile); err != nil {
		logger.ErrorCF("voice", "Failed to copy file content", map[string]any{"error": err})
		return nil, fmt.Errorf("failed to copy file content: %w", err)
	}

	if err = writer.WriteField("model_id", t.modelID); err != nil {
		return nil, fmt.Errorf("failed to write model_id field: %w", err)
	}

	if err = writer.Close(); err != nil {
		logger.ErrorCF("voice", "Failed to close multipart writer", map[string]any{"error": err})
		return nil, fmt.Errorf("failed to close multipart writer: %w", err)
	}

	url := t.apiBase + "/v1/speech-to-text"
	req, err := http.NewRequestWithContext(ctx, "POST", url, &requestBody)
	if err != nil {
		logger.ErrorCF("voice", "Failed to create request", map[string]any{"error": err})
		return nil, fmt.Errorf("failed to create request: %w", err)
	}

	req.Header.Set("Content-Type", writer.FormDataContentType())
	req.Header.Set("Xi-Api-Key", t.apiKey)

	logger.DebugCF("voice", "Sending transcription request to ElevenLabs API", map[string]any{
		"url":                url,
		"request_size_bytes": requestBody.Len(),
		"file_size_bytes":    fileInfo.Size(),
	})

	resp, err := t.httpClient.Do(req)
	if err != nil {
		logger.ErrorCF("voice", "Failed to send request", map[string]any{"error": err})
		return nil, fmt.Errorf("failed to send request: %w", err)
	}
	defer resp.Body.Close()

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Print the apiBase value with %q to expose hidden whitespace/newlines, then fix the config source.
  2. Validate the base URL once at construction: url.Parse and require a host and http(s) scheme.
  3. Omit apiBase to use the default https://api.elevenlabs.io if unsure.

Example fix

// before
tr := asr.NewElevenLabsTranscriber(key, os.Getenv("EL_BASE"), "")

// after
base := strings.TrimSpace(os.Getenv("EL_BASE"))
if base != "" {
    u, err := url.Parse(base)
    if err != nil || u.Host == "" || (u.Scheme != "http" && u.Scheme != "https") {
        return nil, fmt.Errorf("invalid ElevenLabs api base %q", base)
    }
}
tr := asr.NewElevenLabsTranscriber(key, base, "")
Defensive patterns

Strategy: validation

Validate before calling

func validAPIBase(base string) error {
    if base == "" { return nil } // constructor defaults to https://api.elevenlabs.io
    u, err := url.Parse(strings.TrimSpace(base))
    if err != nil { return fmt.Errorf("unparseable api base: %w", err) }
    if u.Host == "" || (u.Scheme != "http" && u.Scheme != "https") {
        return fmt.Errorf("api base missing scheme/host: %q", base)
    }
    return nil
}

Type guard

func isURLParseErr(err error) bool {
    var ue *url.Error
    return errors.As(err, &ue) && ue.Op == "parse"
}

Try / catch

if _, err := el.Transcribe(ctx, path); err != nil {
    if isURLParseErr(err) {
        return fmt.Errorf("ElevenLabs apiBase misconfigured (%q): fix the env/config value", baseCfg)
    }
    return err
}

Prevention

When it happens

Trigger: apiBase passed to NewElevenLabsTranscriber contains whitespace, a trailing newline (env var read with newline), missing scheme (api.elevenlabs.io instead of https://...), or an unreachable-to-parse string. Note the constructor defaults to https://api.elevenlabs.io only when apiBase is empty.

Common situations: ELEVENLABS_API_BASE-style config value with trailing \r (Windows-edited config) or missing scheme; proxy endpoint URL typo; environment variable interpolation inserting quotes.

Related errors


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/de8683724b346edc. Report an issue: GitHub.