{"record":{"id":"e1a84787b5f3c351","repo":"charmbracelet/crush","slug":"failed-to-create-request-w-e1a847","errorCode":null,"errorMessage":"failed to create request: %w","messagePattern":"failed to create request: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/agent/tools/fetch.go","lineNumber":115,"sourceCode":"\t\t\t}\n\n\t\t\t// maxFetchTimeoutSeconds is the maximum allowed timeout for fetch requests (2 minutes)\n\t\t\tconst maxFetchTimeoutSeconds = 120\n\n\t\t\t// Handle timeout with context\n\t\t\trequestCtx := ctx\n\t\t\tif params.Timeout > 0 {\n\t\t\t\tif params.Timeout > maxFetchTimeoutSeconds {\n\t\t\t\t\tparams.Timeout = maxFetchTimeoutSeconds\n\t\t\t\t}\n\t\t\t\tvar cancel context.CancelFunc\n\t\t\t\trequestCtx, cancel = context.WithTimeout(ctx, time.Duration(params.Timeout)*time.Second)\n\t\t\t\tdefer cancel()\n\t\t\t}\n\n\t\t\treq, err := http.NewRequestWithContext(requestCtx, \"GET\", params.URL, nil)\n\t\t\tif err != nil {\n\t\t\t\treturn fantasy.ToolResponse{}, fmt.Errorf(\"failed to create request: %w\", err)\n\t\t\t}\n\n\t\t\treq.Header.Set(\"User-Agent\", \"crush/1.0\")\n\n\t\t\tresp, err := client.Do(req)\n\t\t\tif err != nil {\n\t\t\t\treturn fantasy.ToolResponse{}, fmt.Errorf(\"failed to fetch URL: %w\", err)\n\t\t\t}\n\t\t\tdefer resp.Body.Close()\n\n\t\t\tif resp.StatusCode != http.StatusOK {\n\t\t\t\treturn fantasy.NewTextErrorResponse(fmt.Sprintf(\"Request failed with status code: %d\", resp.StatusCode)), nil\n\t\t\t}\n\n\t\t\tbody, err := io.ReadAll(io.LimitReader(resp.Body, MaxFetchSize))\n\t\t\tif err != nil {\n\t\t\t\treturn fantasy.NewTextErrorResponse(\"Failed to read response body: \" + err.Error()), nil\n\t\t\t}","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/agent/tools/fetch.go#L97-L133","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the wrapped %w cause for the exact parse error and fix the URL accordingly.","URL-encode the address (url.QueryEscape / neturl.PathEscape for components) before passing it.","Strip whitespace and trailing punctuation from the URL.","Validate with url.ParseRequestURI in calling code before invoking the tool."],"exampleFix":"// before\n{\"url\": \"https://example.com/search?q=go pointers\"}\n// after: percent-encode the space\n{\"url\": \"https://example.com/search?q=go%20pointers\"}","handlingStrategy":"validation","validationCode":"func validateURL(raw string) error {\n\tu, err := url.ParseRequestURI(raw)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid URL: %w\", err)\n\t}\n\tif u.Scheme != \"http\" && u.Scheme != \"https\" {\n\t\treturn errors.New(\"scheme must be http/https\")\n\t}\n\treturn nil\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"failed to create request\") {\n\t// re-encode the URL (escape spaces/control chars) and retry once\n}","preventionTips":["Percent-encode spaces and special characters in URLs before use.","Strip whitespace and trailing punctuation from pasted/generated URLs.","Pre-validate with url.ParseRequestURI before invoking the fetch tool.","Keep timeouts positive and sane (seconds, not negative)."],"tags":["http","url","network","fetch-tool"],"backgroundTag":"invalid-url","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}