HTTP client used without a timeout

An HTTP request is made using the package-level `http.Get` / `http.Post` functions or an empty `&http.Client{}` literal — neither sets a timeout, so the call can hang indefinitely if the server is slow or unresponsive.

http-client-no-timeout high confidence runtime go

HTTP client used without a timeout

What this failure means

An HTTP request is made using the package-level http.Get / http.Post functions or an empty &http.Client{} literal — neither sets a timeout, so the call can hang indefinitely if the server is slow or unresponsive.

Diagnosis

The package-level http.Get, http.Post, or http.DefaultClient all rely on a default http.Client with Timeout: 0 (no timeout). A call to a slow or unreachable server will block the goroutine until the OS TCP timeout fires — typically tens of minutes.

Common patterns:

  • resp, err := http.Get(url) — uses DefaultClient with no timeout
  • resp, err := http.Post(url, ...) — uses DefaultClient with no timeout
  • client := &http.Client{} followed by client.Do(req) — Timeout is zero

In production services, this causes goroutine exhaustion, request queue buildup, and cascading timeouts across all downstream callers.

Fix steps

  1. Create a client with a timeout appropriate for the operation:
    client := &http.Client{Timeout: 10 * time.Second}
    resp, err := client.Get(url)
    
  2. For per-request control, use a context with a deadline:
    ctx, cancel := context.WithTimeout(ctx, 10*time.Second)
    defer cancel()
    req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
    if err != nil { return nil, err }
    resp, err := client.Do(req)
    
  3. Define timeouts as named constants or environment-driven configuration so they can be tuned without a code change.
  4. Avoid using http.DefaultClient in any production code path.

Validation

  • Run faultline inspect . from the repository root and confirm this source finding is absent or intentionally mitigated.
  • Add a test that confirms the client respects the configured timeout by pointing it at a handler that delays its response.

Why it matters

A single stuck HTTP call can saturate a goroutine pool. Without a timeout, a slow dependency becomes a liveness threat: incoming requests accumulate waiting for a free goroutine, memory grows, and eventually the process is killed or stops responding to health checks.

Try it locally

make test
rg -n 'http.Get\|http.Post\|http.DefaultClient' .
make test
go vet ./...

How Faultline detects it

Use faultline explain http-client-no-timeout to see the full playbook.

faultline analyze build.log
faultline explain http-client-no-timeout

Generated from playbooks/bundled/source/http-client-no-timeout.yaml. Do not edit directly.

Try it on your own failed log

$ faultline analyze failed.log
Want this across every CI run? Faultline Teams tracks recurring failures across all your repos and surfaces patterns in a shared dashboard.