# Command Timeout (/sdks/elixir/how-to/rpc/command-timeout)



## Overview [#overview]

A **command timeout** is the deadline you attach to a single RPC call so a caller never blocks forever waiting on a handler that isn't there or isn't responding. Commands are synchronous by design — the sender is parked until a reply arrives — so without a bound, a missing subscriber or a crashed handler turns one request into an indefinite hang that ties up the calling process and cascades into upstream timeouts.

The timeout is set per call with `timeout` on `KubeMQ.Command.new`, and it's enforced by the broker itself, not by client-side polling: the broker tracks the deadline server-side and fails the request the moment it expires, regardless of what the calling process is doing. When the window elapses with no response, `KubeMQ.Client.send_command/2` returns `{:error, err}` with `err.code` set to `:timeout` — your signal to retry or fall back.

**Gotchas:** a command timeout is a broker-enforced deadline, not a local `GenServer.call` timeout, so don't assume a local call timing out means the broker also gave up; a slow-but-alive handler and a completely absent one produce the *same* `:timeout` code, so you can't tell them apart from the error alone; and check `err.retryable?` before retrying — not every timeout is safe to resend blindly.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Elixir SDK installed (`{:kubemq, "~> 1.0"}` in mix.exs)

## Code [#code]

```elixir title="main.exs"
channel = "elixir-rpc.command-timeout"
{:ok, client} = KubeMQ.Client.start_link(address: "localhost:50000", client_id: "elixir-cmd-timeout")

IO.puts("Sending command with 3-second timeout (no handler)...")

cmd = KubeMQ.Command.new(
  channel: channel,
  body: "this will timeout",
  timeout: 3_000
)

case KubeMQ.Client.send_command(client, cmd) do
  {:ok, response} ->
    if response.error do
      IO.puts("Command returned with error: #{response.error}")
    else
      IO.puts("Command executed: #{response.executed}")
    end

  {:error, err} ->
    IO.puts("Command timed out or failed: #{err.message}")
    IO.puts("Error code: #{err.code}")
end

IO.puts("Timeout handling complete.")
KubeMQ.Client.close(client)
```

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

* When no handler is subscribed, `send_command/2` blocks for the `timeout` duration
* After the timeout, an error is returned with code `:timeout`
* The `retryable?` field on the error indicates whether the operation can be retried

## Related [#related]

* [Send Command](/sdks/elixir/tutorials/command-send)
* [Reconnection](/sdks/elixir/how-to/error-handling/reconnection)
