Troubleshooting & FAQ
Frequently Asked Questions
Do I need to install Akka.NET separately?
No. Akka.NET is a transitive dependency of TurboHTTP — it is pulled in automatically when you install the package.
Can I use TurboHTTP alongside HttpClient?
Yes. Both can coexist in the same application. Use IHttpClientFactory for your existing services and ITurboHttpClientFactory for new ones. See Gradual Migration.
Is TurboHTTP thread-safe?
Yes. ITurboHttpClient is fully thread-safe. Multiple threads can call SendAsync concurrently. The channel-based API (Requests / Responses) supports concurrent producers and consumers.
How do I disable a feature?
Features are opt-in via the builder API. Simply don't call the corresponding builder method:
// No retries, no caching, no redirects — just register without builder extensions
builder.Services.AddTurboHttpClient("bare", options =>
{
options.BaseAddress = new Uri("https://api.example.com");
});Does TurboHTTP support HTTPS?
Yes. TLS is handled automatically for https:// URIs. Configure TLS options via TurboClientOptions:
options.EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13;
options.ClientCertificates = new X509CertificateCollection { cert };What HTTP versions are supported?
HTTP/1.0, HTTP/1.1, HTTP/2, and HTTP/3 (QUIC). Set the version on the client:
var client = factory.CreateClient("my-api");
client.DefaultRequestVersion = HttpVersion.Version20; // or Version11, Version10, Version30Per-request overrides are also supported via HttpRequestMessage.Version.
Common Issues
Connection Refused / Timeout
Symptom: SendAsync throws a timeout or connection exception.
Causes:
- Server is not reachable — verify the URL and network
ConnectTimeouttoo low — increase it:csharpoptions.ConnectTimeout = TimeSpan.FromSeconds(30);- DNS resolution failure — check hostname spelling
- Firewall blocking the port
Too Many Redirects
Symptom: RedirectException with RedirectError.MaxRedirectsExceeded.
Fix: The server is returning a redirect loop. Either fix the server or increase the redirect limit via the builder:
builder.Services.AddTurboHttpClient("my-api", options =>
{
options.BaseAddress = new Uri("https://api.example.com");
})
.WithRedirect(redirect => { redirect.MaxRedirects = 20; });To debug, remove the .WithRedirect() call entirely and inspect the redirect responses manually.
HTTPS to HTTP Downgrade Blocked
Symptom: RedirectException with RedirectError.ProtocolDowngrade on a redirect.
Cause: A server redirected from https:// to http://, which TurboHTTP blocks by default for security.
Fix (if the downgrade is intentional):
builder.Services.AddTurboHttpClient("my-api", options =>
{
options.BaseAddress = new Uri("https://api.example.com");
})
.WithRedirect(redirect => { redirect.AllowHttpsToHttpDowngrade = true; });POST Requests Are Not Retried
By design. POST is not idempotent — retrying it could create duplicate resources. Only idempotent methods (GET, HEAD, PUT, DELETE, OPTIONS, TRACE) are retried automatically.
If you need to retry POST, configure a custom retry policy via the builder:
builder.Services.AddTurboHttpClient("my-client", options =>
{
options.BaseAddress = new Uri("https://api.example.com");
})
.WithRetry(retry => { retry.MaxRetries = 3; });The built-in retry handles idempotent method detection and backoff automatically.
High Memory Usage
Possible causes:
- Cache too large — reduce
MaxEntriesorMaxBodyByteswhen registering:csharp.WithCache(c => { c.MaxEntries = 100; c.MaxBodyBytes = 10 * 1024 * 1024; }) - Response bodies not disposed — always dispose
HttpResponseMessagewhen done:csharpusing var response = await client.SendAsync(request, ct); - CookieJar accumulating — clear periodically if needed:csharp
cookieJar.Clear();
HTTP/2 Connection Failures
Symptom: HTTP/2 request fails, HTTP/1.1 works.
Possible causes:
- Server doesn't support HTTP/2 — use
HttpVersionPolicy.RequestVersionOrLowerto fall back - Cleartext HTTP/2 (h2c) not supported by server — use HTTPS
- TLS ALPN negotiation failed — check server TLS configuration
var client = factory.CreateClient("my-api");
client.DefaultRequestVersion = HttpVersion.Version20;
client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrLower; // graceful fallbackChannel Backpressure (WriteAsync Blocks)
Symptom: Requests.WriteAsync hangs.
Cause: The outbound channel is full — the connection cannot send requests as fast as you produce them. This is correct behaviour (backpressure).
Fixes:
- Use HTTP/2 for multiplexing (concurrent streams over one connection)
- Increase
MaxConnectionsPerServerfor HTTP/1.1:csharpoptions.Http1.MaxConnectionsPerServer = 16; - Ensure consumer task is actively reading responses to unblock the producer
Stale Cache Responses
Symptom: Getting old data despite server changes.
Fixes:
- Force revalidation on a specific request:csharp
request.Headers.CacheControl = new CacheControlHeaderValue { NoCache = true }; - Bypass cache entirely:csharp
request.Headers.CacheControl = new CacheControlHeaderValue { NoStore = true }; - Reduce cache size when registering:csharp
.WithCache(c => { c.MaxEntries = 100; })
Debugging Tips
Enable Akka Logging
TurboHTTP uses Akka's logging infrastructure. To see connection lifecycle events:
// In your Akka configuration
akka.loglevel = DEBUG
akka.actor.debug.lifecycle = onInspect Connection State
The actor hierarchy provides connection pool visibility. Use Akka's built-in monitoring to see:
- Active connections per host
- Idle connection count
- Reconnect attempts
Capture Wire Traffic
For protocol-level debugging, capture TCP traffic with Wireshark or a proxy:
// Route through a debugging proxy (e.g., Fiddler, mitmproxy)
options.BaseAddress = new Uri("http://localhost:8080"); // proxy addressFor HTTP/2, use a tool that understands binary framing (e.g., Wireshark with HTTP/2 dissector).