# Network & Transport Errors

Transport errors are failures that happen before the server can respond: connection refused or reset, request timeout, DNS lookup failure, TLS handshake failure. The SDK catches these at the HTTP-client boundary and re-emits them as a typed transport exception with a categorized `errorType`. The original error is preserved on the cause chain.

This means callers do not have to catch `httpx.RequestError`, `HttpRequestException`, `Faraday::Error`, `GuzzleException`, `IOException`, or `net.Error` separately. One `catch` block covers all transport-layer failures.

## The errorType enum

| Value                  | When the SDK uses it                                                      |
| ---------------------- | ------------------------------------------------------------------------- |
| `connection_reset`     | Connection refused, reset, or closed prematurely.                         |
| `timeout`              | Read, write, or wall-clock deadline exceeded.                             |
| `dns_failure`          | Could not resolve the host.                                               |
| `tls_handshake_failed` | TLS / SSL handshake failed (certificate verify, protocol mismatch, etc.). |
| `unknown`              | Could not be classified into one of the above.                            |

The transport exception always exposes the underlying error via the language-native cause-chain accessor.

## Catching transport errors

<Tabs>

```python label="Python"
from getstream.exceptions import StreamTransportException

try:
    client.do_something()
except StreamTransportException as e:
    # e.error_type is one of connection_reset / timeout / dns_failure / tls_handshake_failed / unknown
    # e.__cause__ is the underlying httpx exception
    if e.error_type == "timeout":
        # back off and try again later
        ...
```

```go label="Go"
import (
    "errors"
    "github.com/GetStream/getstream-go/v4"
)

_, err := client.DoSomething(ctx, ...)
if errors.Is(err, getstream.ErrTransport) {
    var streamErr *getstream.StreamError
    errors.As(err, &streamErr)
    // streamErr.ErrorType is one of connection_reset / timeout / dns_failure / tls_handshake_failed / unknown
    // errors.Unwrap(err) returns the underlying transport error
    if streamErr.ErrorType == "timeout" {
        // back off and try again later
    }
}
```

```csharp label="C#"
using GetStream;

try
{
    await client.DoSomethingAsync();
}
catch (GetStreamTransportException ex)
{
    // ex.ErrorType is one of connection_reset / timeout / dns_failure / tls_handshake_failed / unknown
    // ex.InnerException is the underlying HttpRequestException / TaskCanceledException / etc.
    if (ex.ErrorType == "timeout")
    {
        // back off and try again later
    }
}
```

```java label="Java"
import io.getstream.exceptions.StreamTransportException;

try {
    client.doSomething();
} catch (StreamTransportException e) {
    // e.getErrorType() is one of connection_reset / timeout / dns_failure / tls_handshake_failed / unknown
    // e.getCause() is the underlying IOException
    if ("timeout".equals(e.getErrorType())) {
        // back off and try again later
    }
}
```

```php label="PHP"
use GetStream\Exceptions\StreamTransportException;

try {
    $client->doSomething();
} catch (StreamTransportException $e) {
    // $e->getErrorType() is one of connection_reset / timeout / dns_failure / tls_handshake_failed / unknown
    // $e->getPrevious() is the underlying Guzzle exception
    if ($e->getErrorType() === 'timeout') {
        // back off and try again later
    }
}
```

```ruby label="Ruby"
begin
  client.do_something
rescue GetStreamRuby::TransportError => e
  # e.error_type is one of connection_reset / timeout / dns_failure / tls_handshake_failed / unknown
  # e.cause is the underlying Faraday error
  if e.error_type == 'timeout'
    # back off and try again later
  end
end
```

</Tabs>

## Distinguishing transport errors from API errors

Transport errors happen when no HTTP response was received. API errors happen when the server responded with a 4xx or 5xx. Catch them separately if you want to react differently:

<Tabs>

```python label="Python"
from getstream.exceptions import StreamApiException, StreamTransportException

try:
    client.do_something()
except StreamApiException as e:
    # server responded with a 4xx/5xx
    handle_api_error(e)
except StreamTransportException as e:
    # network or transport-layer failure
    handle_transport_error(e)
```

```go label="Go"
_, err := client.DoSomething(ctx, ...)
if errors.Is(err, getstream.ErrApiResponse) {
    // server responded with a 4xx/5xx
} else if errors.Is(err, getstream.ErrTransport) {
    // network or transport-layer failure
}
```

</Tabs>

Both transport and API exceptions inherit from the SDK's base exception. Catch that base type if you want to handle all SDK-emitted errors uniformly. See [Exception Handling](/chat/docs/java/exception-handling/) for the full class hierarchy.


---

This page was last updated at 2026-06-01T14:18:50.700Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/java/transport-errors/](https://getstream.io/chat/docs/java/transport-errors/).