affaan-m/ECC · error

create request: %w

Error message

create request: %w

What it means

Wrapped error from FetchWithTimeout in golang-patterns. After building a context with timeout, http.NewRequestWithContext is called; if request construction fails the error is wrapped as fmt.Errorf("create request: %w", err). This step does no networking - it only validates the method, url, and header values - so failure here means the inputs to the request were invalid, not that the server was unreachable.

Source

Thrown at skills/golang-patterns/SKILL.md:207

            }
        }()
    }

    wg.Wait()
    close(results)
}
```

### Context for Cancellation and Timeouts

```go
func FetchWithTimeout(ctx context.Context, url string) ([]byte, error) {
    ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
    defer cancel()

    req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
    if err != nil {
        return nil, fmt.Errorf("create request: %w", err)
    }

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, fmt.Errorf("fetch %s: %w", url, err)
    }
    defer resp.Body.Close()

    return io.ReadAll(resp.Body)
}
```

### Graceful Shutdown

```go
func GracefulShutdown(server *http.Server) {
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Validate the URL with net/url.Parse and check u.Err / scheme + host before constructing the request.
  2. Sanitize or reject any header value containing CR/LF or control characters.
  3. Default the scheme to https when missing.
  4. Treat request-construction errors as programmer/input errors (4xx-style), not transient failures.

Example fix

// before
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
    return nil, fmt.Errorf("create request: %w", err)
}

// after
u, err := url.Parse(url)
if err != nil || u.Scheme == "" || u.Host == "" {
    return nil, fmt.Errorf("invalid url %q: %w", url, err)
}
req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
if err != nil {
    return nil, fmt.Errorf("create request: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

func validateRequestInputs(method, urlStr string, headers http.Header) error {
    if !validMethod(method) {
        return fmt.Errorf("invalid method %q", method)
    }
    u, err := url.Parse(urlStr)
    if err != nil || u.Scheme == "" || u.Host == "" {
        return fmt.Errorf("invalid url %q", urlStr)
    }
    for k, vs := range headers {
        for _, v := range vs {
            if strings.ContainsAny(v, "\r\n") {
                return fmt.Errorf("header %s contains CRLF", k)
            }
        }
    }
    return nil
}

Type guard

func isInvalidURL(err error) bool {
    var ue *url.Error
    return errors.As(err, &ue)
}

Try / catch

req, err := http.NewRequestWithContext(ctx, method, urlStr, nil)
if err != nil {
    if isInvalidURL(err) {
        return BadRequest("invalid url")
    }
    return InternalError(err)
}

Prevention

When it happens

Trigger: Calling FetchWithTimeout(ctx, url) when http.NewRequestWithContext returns an error. Concrete triggers: the url is empty, contains spaces or control characters, is missing a scheme/host, the method is invalid, or a header value contains a CR/LF or other disallowed octet.

Common situations: URL built from unsanitized user input; missing scheme ("example.com" instead of "https://example.com"); a header derived from user data that contains a newline (header injection); wrong HTTP method constant; copy-paste left a placeholder URL.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/b3d05fb0e6b1e172. Report an issue: GitHub.