# Command Timeout (/sdks/csharp/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 an awaited task and cascades into upstream timeouts.

The timeout is set per call with `TimeoutInSeconds` on `CommandMessage`, 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 task is doing. When the window elapses with no response, `SendCommandAsync` throws a `KubeMQTimeoutException` — a specific exception type that's your signal to retry or fall back.

**Gotchas:** a slow-but-alive handler and a completely absent one produce the *same* timeout behavior, so you can't tell them apart from the exception alone; setting `TimeoutInSeconds` too short under normal load turns transient latency into false failures; and command/query calls are not retried on timeout (they're non-idempotent), so a `KubeMQTimeoutException` here means the SDK gave up after this one attempt, not after a hidden retry loop.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* C# SDK installed (`dotnet add package KubeMQ.SDK.CSharp`)

## Code [#code]

```csharp title="Program.cs"
// KubeMQ .NET SDK — Commands: Timeout Handling
//
// This example demonstrates how command timeouts work. A command is sent with
// a short timeout and no handler is running, so it times out. The SDK surfaces
// this as a KubeMQTimeoutException.
//
// Prerequisites:
//   - KubeMQ server running on localhost:50000
//   - Do NOT start a command handler — this example expects a timeout
//   - dotnet run

using KubeMQ.Sdk.Client;
using KubeMQ.Sdk.Commands;
using KubeMQ.Sdk.Exceptions;
using System.Text;

await using var client = new KubeMQClient(new KubeMQClientOptions
{
    Address = "localhost:50000",
    ClientId = "csharp-commands-command-timeout-client",
});
await client.ConnectAsync();
Console.WriteLine("Connected to KubeMQ server");

int[] timeouts = [2, 5];

foreach (var timeout in timeouts)
{
    Console.WriteLine($"\nSending command with {timeout}s timeout (no handler running)...");
    try
    {
        var response = await client.SendCommandAsync(new CommandMessage
        {
            Channel = "csharp-commands.command-timeout",
            Body = Encoding.UTF8.GetBytes($"action-with-{timeout}s-timeout"),
            TimeoutInSeconds = timeout,
        });

        Console.WriteLine($"  Executed: {response.Executed}");
        if (!string.IsNullOrEmpty(response.Error))
        {
            Console.WriteLine($"  Error: {response.Error}");
        }
    }
    catch (KubeMQTimeoutException ex)
    {
        Console.WriteLine($"  Caught KubeMQTimeoutException: {ex.Message}");
    }
    catch (KubeMQException ex)
    {
        Console.WriteLine($"  Caught KubeMQException: {ex.Message}");
    }
}

Console.WriteLine("\nDone.");

```

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

* No handler is running for this channel, so both commands time out as expected. The first command waits 2 seconds; the second waits 5 seconds.
* A timed-out command or query always raises `KubeMQTimeoutException` — the second `catch (KubeMQException)` is a defensive fallback for other operation errors (e.g. validation), not an alternate timeout path.
* `TimeoutInSeconds` is the maximum time the broker waits for a handler to respond. Set it based on the expected processing time of your handler plus network latency.
* To test successful command execution, start the Handle Command example in a separate terminal before running this program.

## Related [#related]

* [Pattern overview](/learn/rpc/getting-started)
* [C# SDK Reference](/sdks/csharp/reference)
* [Send Command](/sdks/csharp/tutorials/command-send)
* [Handle Command](/sdks/csharp/how-to/rpc/command-handle)
