# Command Timeout (/sdks/go/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 a goroutine and cascades into upstream timeouts.

The timeout is set per call with `SetTimeout` on the command, 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 client's own context is doing. When the window elapses with no response, `SendCommand` returns a non-nil error instead of a reply — your signal to retry or fall back.

**Gotchas:** a command timeout and the client's context deadline are two separate clocks, so don't assume one implies the other; a slow-but-alive handler and a completely absent one produce the *same* timeout error, so you can't tell them apart from the error alone; and setting the timeout too short under normal load turns transient latency into false failures.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Go SDK installed (`go get github.com/kubemq-io/kubemq-go/v2`)

## Code [#code]

```go title="main.go"
// Example: commands/command-timeout
//
// Demonstrates command timeout handling. When no handler responds
// within the timeout period, the SendCommand call returns an error.
//
// Channel: go-commands.command-timeout
// Client ID: go-commands-command-timeout-client
//
// Run with a KubeMQ server on localhost:50000
// (see https://docs.kubemq.io/deploy).
package main

import (
	"context"
	"fmt"
	"log"
	"time"

	"github.com/kubemq-io/kubemq-go/v2"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	client, err := kubemq.NewClient(ctx,
		kubemq.WithAddress("localhost", 50000),
		kubemq.WithClientId("go-commands-command-timeout-client"),
	)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	// Send a command to a channel with no handler — it will timeout.
	_, err = client.SendCommand(ctx, kubemq.NewCommand().
		SetChannel("go-commands.command-timeout").
		SetBody([]byte("will timeout")).
		SetTimeout(2*time.Second))
	if err != nil {
		fmt.Printf("Command timed out as expected: %v\n", err)
	} else {
		fmt.Println("Unexpected: command succeeded without a handler")
	}
}

```

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

1. `kubemq.NewCommand().SetTimeout(2*time.Second)` sets a 2-second timeout on the command; the broker enforces this deadline server-side, not the Go context.
2. Because there is no subscriber on `go-commands.command-timeout`, the broker waits the full timeout period before returning an error to `SendCommand`.
3. `SendCommand` returns a non-nil error (typically containing "timeout") when no handler responds within the timeout; `cmdResp` will be `nil` in this case.
4. Command timeouts are distinct from context cancellations: `SetTimeout` is a per-request broker-enforced deadline, while the `ctx` timeout governs the overall client-side blocking call.

## Related [#related]

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