charmbracelet/crush · error

failed to create request: %w

Error message

failed to create request: %w

What it means

The fetch tool builds a GET request with http.NewRequestWithContext and wraps construction failures in this error. Unlike transport errors (which happen later at client.Do), this fails synchronously while parsing the URL or building the request object.

Source

Thrown at internal/agent/tools/fetch.go:115

			}

			// maxFetchTimeoutSeconds is the maximum allowed timeout for fetch requests (2 minutes)
			const maxFetchTimeoutSeconds = 120

			// Handle timeout with context
			requestCtx := ctx
			if params.Timeout > 0 {
				if params.Timeout > maxFetchTimeoutSeconds {
					params.Timeout = maxFetchTimeoutSeconds
				}
				var cancel context.CancelFunc
				requestCtx, cancel = context.WithTimeout(ctx, time.Duration(params.Timeout)*time.Second)
				defer cancel()
			}

			req, err := http.NewRequestWithContext(requestCtx, "GET", params.URL, nil)
			if err != nil {
				return fantasy.ToolResponse{}, fmt.Errorf("failed to create request: %w", err)
			}

			req.Header.Set("User-Agent", "crush/1.0")

			resp, err := client.Do(req)
			if err != nil {
				return fantasy.ToolResponse{}, fmt.Errorf("failed to fetch URL: %w", err)
			}
			defer resp.Body.Close()

			if resp.StatusCode != http.StatusOK {
				return fantasy.NewTextErrorResponse(fmt.Sprintf("Request failed with status code: %d", resp.StatusCode)), nil
			}

			body, err := io.ReadAll(io.LimitReader(resp.Body, MaxFetchSize))
			if err != nil {
				return fantasy.NewTextErrorResponse("Failed to read response body: " + err.Error()), nil
			}

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Inspect the wrapped %w cause for the exact parse error and fix the URL accordingly.
  2. URL-encode the address (url.QueryEscape / neturl.PathEscape for components) before passing it.
  3. Strip whitespace and trailing punctuation from the URL.
  4. Validate with url.ParseRequestURI in calling code before invoking the tool.

Example fix

// before
{"url": "https://example.com/search?q=go pointers"}
// after: percent-encode the space
{"url": "https://example.com/search?q=go%20pointers"}
Defensive patterns

Strategy: validation

Validate before calling

func validateURL(raw string) error {
	u, err := url.ParseRequestURI(raw)
	if err != nil {
		return fmt.Errorf("invalid URL: %w", err)
	}
	if u.Scheme != "http" && u.Scheme != "https" {
		return errors.New("scheme must be http/https")
	}
	return nil
}

Try / catch

if strings.Contains(err.Error(), "failed to create request") {
	// re-encode the URL (escape spaces/control chars) and retry once
}

Prevention

When it happens

Trigger: params.URL failing url.Parse — malformed URLs like 'http://[invalid', URLs with spaces or unescaped control characters, or a negative/invalid timeout producing a bad context path.

Common situations: LLM-generated URLs containing spaces or illegal characters, missing scheme variants slipping through (though http/https is pre-checked), hosts with unescaped Unicode, or copy-pasted URLs with trailing punctuation.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/e1a84787b5f3c351. Report an issue: GitHub.