When you run a load test and see transport errors in your report, it's tempting to just look at the percentage and move on. But understanding what happened and why gives you actionable information about your target's health and infrastructure.

Transport errors are fundamentally different from HTTP errors. An HTTP 500 means the server received your request, tried to process it, and failed. A transport error means the connection itself broke — no HTTP response was ever received.

Client ─── TCP SYN ───▶ Server
Client ◀── SYN-ACK ─── Server
Client ─── ACK + HTTP GET ─▶ Server

Client ◀── HTTP 200 OK ─── Server   ✓ Success

vs.

Client ─── TCP SYN ───▶ Server
Client ◀── RST (Connection Refused)   ✗ Transport Error

The Four Transport Errors

deadline_exceeded Timeout

The request was sent, but the server didn't respond within the timeout window (default: 2 seconds).

What it means: The TCP connection was established, but the server took too long to send back a complete HTTP response. This could be slow database queries, thread pool exhaustion, or the server processing a very large payload.
connection_refused Rejected

The server actively rejected the TCP connection. No handshake completed.

What it means: The target port is closed or the server's backlog queue is full. Common causes: server is down, max connections reached, firewall rules, or the process crashed mid-test.
connection_reset Dropped

The server closed the connection abruptly with a TCP RST packet.

What it means: The connection was established, but the server terminated it mid-stream. This happens when the server process crashes, a load balancer times out, or the OS kills the socket due to resource limits (e.g., too many open files).
EOF / broken_pipe Closed

The server closed the connection before sending a complete response.

What it means: The connection was open, but the server closed its end prematurely. Unlike connection_reset (which is abrupt), this is a "clean" close — the server decided to stop talking. Common in keep-alive connections, reverse proxies, or when the server enforces a request timeout shorter than your load test timeout.

How GoStress Classifies Errors

GoStress categorizes every failed request into one of two buckets:

This distinction matters because the remediation is different. HTTP failures usually mean you need to fix application logic or reduce load. Transport errors usually mean infrastructure is at capacity or something crashed.

Interpreting Error Rates

Transport Error % Severity Likely Cause
0-5%NormalOccasional timeouts under load, expected
5-20%ModerateServer approaching capacity, check connection pools
20%+HighServer overloaded or infrastructure failure

When 100% of errors are deadline_exceeded: Your timeout is likely too short for the server's actual response time. Try --timeout 5s or check if the server is experiencing database latency or external service dependencies.

When errors increase over time: This usually means the server is degrading under sustained load — connection pools draining, memory pressure, or thread starvation. Use --ramp to find the exact concurrency where errors start.

Practical Next Steps

When you see transport errors in your GoStress report:

  1. Check the error type breakdown — The report lists each error type with its count
  2. Look at when errors started — If they increase over time, it's load-induced degradation
  3. Compare with latency — High p99 + deadline_exceeded = server is slow, not down
  4. Reduce concurrency — If errors drop, you found the capacity ceiling
  5. Check server logs — Transport errors at the client correlate with resource exhaustion at the server
# Find where errors start by ramping gradually
gostress --url https://api.example.com --c 300 --d 60 --ramp 30

# Watch the progress bar — note the concurrency level when errors appear
Test Progress: 15.0% | Concurrency: 90   ✓ no errors
Test Progress: 18.3% | Concurrency: 110  ⚠ first deadline_exceeded
Test Progress: 21.7% | Concurrency: 130  ✗ 3 deadline_exceeded