# Connection Error (/sdks/elixir/how-to/error-handling/connection-error)



## Overview [#overview]

A network partition, a server that hasn't started yet, or a typo in the address are all normal facts of life in distributed systems — and a client that blocks indefinitely or crashes turns a routine outage into a cascading failure. **Fail-fast connection checking** lets you detect an unreachable KubeMQ server the moment you call `start_link/1`, so your service can log the failure, alert, or fall back instead of hanging.

`KubeMQ.Client.start_link/1` returns `{:error, reason}` immediately when the server is unreachable, instead of blocking or crashing the calling process. A guard clause like `when is_exception(err)` distinguishes a structured KubeMQ error — carrying `code`, `message`, and `operation` — from an arbitrary term returned as `reason`, so your `case` can pattern-match precisely on the failure shape. &#x2A;*Gotchas:** always match both the structured-exception clause and a catch-all `{:error, reason}` clause, since not every failure reason is a KubeMQ exception struct; a successful `start_link/1` doesn't guarantee the connection stays healthy, so mid-session drops still need reconnection handling; validation errors (like an empty channel) surface the same way as connection errors — inspect `code` before assuming a failed operation means the server is down.

## Prerequisites [#prerequisites]

* Elixir SDK installed (`{:kubemq, "~> 1.0"}` in mix.exs)

## Code [#code]

```elixir title="main.exs"
IO.puts("Attempting connection to unreachable server...")

case KubeMQ.Client.start_link(
       address: "localhost:99999",
       client_id: "elixir-error-example"
     ) do
  {:ok, client} ->
    IO.puts("Connected (unexpected for this demo)")
    KubeMQ.Client.close(client)

  {:error, err} when is_exception(err) ->
    IO.puts("KubeMQ error caught:")
    IO.puts("  Code: #{Map.get(err, :code)}")
    IO.puts("  Message: #{Exception.message(err)}")
    IO.puts("  Operation: #{Map.get(err, :operation)}")

  {:error, reason} ->
    IO.puts("Connection error: #{inspect(reason)}")
end

IO.puts("\nAttempting operation on a valid connection with bad channel...")

case KubeMQ.Client.start_link(
       address: "localhost:50000",
       client_id: "elixir-error-example-2"
     ) do
  {:ok, client} ->
    bad_event = %KubeMQ.Event{channel: "", body: "test"}

    case KubeMQ.Client.send_event(client, bad_event) do
      :ok -> IO.puts("Sent (unexpected)")
      {:error, err} -> IO.puts("Validation error: #{err.message} (code: #{err.code})")
    end

    KubeMQ.Client.close(client)

  {:error, reason} ->
    IO.puts("Could not connect: #{inspect(reason)}")
end
```

## How It Works [#how-it-works]

* `start_link/1` returns `{:error, reason}` when the server is unreachable
* Guard clauses `when is_exception(err)` distinguish structured errors from raw terms
* Sending to an empty channel triggers a validation error with code `:validation`

## Related [#related]

* [Reconnection](/sdks/elixir/how-to/error-handling/reconnection)
* [Graceful Shutdown](/sdks/elixir/how-to/error-handling/graceful-shutdown)
* [Types & Errors Reference](/sdks/elixir/reference/types-and-errors)
