sipeed/picoclaw · error
failed to create request: %w
Error message
failed to create request: %w
What it means
Returned by WhisperTranscriber.doRequest when http.NewRequestWithContext rejects the POST URL built by transcriptionURL() (apiBase + '/audio/transcriptions'). NewRequestWithContext fails on a malformed URL: missing scheme, whitespace or control characters, or invalid percent-encoding in the configured api_base. The method (POST) and body are always valid.
Source
Thrown at pkg/audio/asr/whisper_transcriber.go:188
if err = writer.Close(); err != nil {
return nil, fmt.Errorf("failed to close multipart writer: %w", err)
}
return t.doRequest(ctx, &requestBody, writer.FormDataContentType(), fileInfo.Size())
}
func (t *WhisperTranscriber) doRequest(
ctx context.Context,
requestBody *bytes.Buffer,
contentType string,
fileSize int64,
) (*TranscriptionResponse, error) {
url := t.transcriptionURL()
req, err := http.NewRequestWithContext(ctx, "POST", url, requestBody)
if err != nil {
logger.ErrorCF("voice", "Failed to create whisper request", map[string]any{"error": err})
return nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", contentType)
if t.apiKey != "" {
req.Header.Set("Authorization", "Bearer "+t.apiKey)
}
logger.DebugCF("voice", "Sending whisper transcription request", map[string]any{
"file_size_bytes": fileSize,
"model": t.modelID,
"provider": t.providerName,
"request_size_bytes": requestBody.Len(),
"url": url,
})
resp, err := t.httpClient.Do(req)
if err != nil {
logger.ErrorCF("voice", "Failed to send whisper request", map[string]any{"error": err})View on GitHub (pinned to 49183d7e8d)
Solutions
- Set api_base to a full URL including scheme, e.g. https://api.groq.com/openai/v1
- Trim whitespace from the api_base config value
- url.Parse the base at startup and fail configuration early
- Log transcriptionURL() output to see the exact string being rejected
Example fix
// before
apiBase := `api.groq.com/openai/v1` // missing scheme -> request creation fails
// after
apiBase := `https://api.groq.com/openai/v1`
if _, err := url.Parse(apiBase); err != nil {
return fmt.Errorf(`invalid api_base: %w`, err)
} Defensive patterns
Strategy: validation
Validate before calling
u, err := url.Parse(strings.TrimSpace(cfg.APIBase))
if err != nil || u.Scheme == `` || u.Host == `` {
return fmt.Errorf(`invalid api_base %q: include scheme and host`, cfg.APIBase)
} Type guard
func isInvalidURL(err error) bool {
return err != nil && (strings.Contains(err.Error(), `invalid URI`) ||
strings.Contains(err.Error(), `missing protocol scheme`) ||
strings.Contains(err.Error(), `invalid control character`))
} Try / catch
if err != nil {
// non-retriable config error: fix api_base (add https://, strip whitespace) before retrying
} Prevention
- Validate api_base with url.Parse once at startup
- Always include the scheme in configured base URLs
- Trim whitespace from config-supplied URLs before use
When it happens
Trigger: api_base configured as 'api.groq.com/openai/v1' without https://; trailing whitespace or newline in the config value; a custom endpoint path with characters that break url.Parse.
Common situations: Hand-edited config files; environment variables for the API base missing the scheme; copy-paste artifacts such as trailing spaces.
Related errors
- create request: %w
- build request: %w
- failed to create request: %w
- Failed to load config
- MCP server ${server.name} requires a URL.
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/554fbac2ba1c5a5f.
Report an issue: GitHub.