micro/go-micro · error

failed to create stream request: %w

Error message

failed to create stream request: %w

What it means

This error is returned by Provider.Stream when building the outgoing POST request to the Anthropic /v1/messages endpoint fails via http.NewRequestWithContext. It wraps the underlying error (e.g. an unparseable URL or invalid context). Because the BaseURL is constructed with string concatenation, a malformed BaseURL is the usual cause.

Source

Thrown at ai/anthropic/anthropic.go:254

// Stream generates a streaming response from Anthropic's Messages SSE API.
func (p *Provider) Stream(ctx context.Context, req *ai.Request, opts ...ai.GenerateOption) (ai.Stream, error) {
	apiReq := map[string]any{
		"model":      p.opts.Model,
		"max_tokens": anthropicMaxTokens(p.opts),
		"system":     cacheableSystem(req.SystemPrompt, nil, p.opts.NoCache),
		"messages":   threadAnthropicMessages(req),
		"stream":     true,
	}
	applyReasoningOptions(apiReq, p.opts)
	reqBody, err := json.Marshal(apiReq)
	if err != nil {
		return nil, fmt.Errorf("failed to marshal stream request: %w", err)
	}

	apiURL := strings.TrimRight(p.opts.BaseURL, "/") + "/v1/messages"
	httpReq, err := http.NewRequestWithContext(ctx, http.MethodPost, apiURL, bytes.NewReader(reqBody))
	if err != nil {
		return nil, fmt.Errorf("failed to create stream request: %w", err)
	}
	httpReq.Header.Set("Content-Type", "application/json")
	httpReq.Header.Set("Accept", "text/event-stream")
	httpReq.Header.Set("x-api-key", p.opts.APIKey)
	httpReq.Header.Set("anthropic-version", "2023-06-01")

	httpResp, err := http.DefaultClient.Do(httpReq)
	if err != nil {
		return nil, fmt.Errorf("stream API request failed: %w", err)
	}
	if httpResp.StatusCode != http.StatusOK {
		defer httpResp.Body.Close()
		respBody, _ := io.ReadAll(httpResp.Body)
		return nil, fmt.Errorf("stream API error (%s): %s", httpResp.Status, string(respBody))
	}
	return &streamReader{body: httpResp.Body, scanner: bufio.NewScanner(httpResp.Body)}, nil
}

View on GitHub (pinned to 24529f1404)

Solutions

  1. Check that opts.BaseURL is a fully qualified URL starting with http:// or https:// and trim whitespace/newlines: strings.TrimSpace(os.Getenv("ANTHROPIC_BASE_URL")).
  2. Print the composed URL (strings.TrimRight(p.opts.BaseURL,"/")+"/v1/messages") and validate it with url.Parse to see the wrapped cause.
  3. Fix the source of the config value — quote handling in .env files, YAML, or shell export that injected bad characters.

Example fix

// before
p, _ := anthropic.New(anthropic.WithBaseURL(os.Getenv("ANTHROPIC_BASE_URL"))) // "api.anthropic.com"
// after
base := strings.TrimSpace(os.Getenv("ANTHROPIC_BASE_URL"))
if !strings.HasPrefix(base, "https://") { base = "https://" + base }
p, _ := anthropic.New(anthropic.WithBaseURL(base))
Defensive patterns

Strategy: validation

Validate before calling

func validateBaseURL(raw string) error {
	u, err := url.Parse(strings.TrimSpace(raw) + "/v1/messages")
	if err != nil { return fmt.Errorf("invalid base URL: %w", err) }
	if u.Scheme != "http" && u.Scheme != "https" { return errors.New("base URL must use http(s)") }
	return nil
}

Try / catch

resp, err := provider.Stream(ctx, req)
if err != nil {
	return fmt.Errorf("stream setup failed (check BaseURL): %w", err)
}

Prevention

When it happens

Trigger: p.opts.BaseURL plus "/v1/messages" is not a valid URL (invalid characters, spaces, bad scheme, control characters), or the passed ctx has been constructed in a way NewRequestWithContext rejects (rare).

Common situations: Misconfigured ANTHROPIC_BASE_URL containing a trailing newline from an env file, a URL missing the scheme (e.g. "api.anthropic.com" instead of "https://api.anthropic.com"), or copying a base URL with surrounding whitespace into config.

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/ff64c0a519d60d81. Report an issue: GitHub.