# Command Timeout (/sdks/java/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 thread 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 terminates the pending request the moment it expires, regardless of what the calling thread is doing. When the window elapses with no response, `sendCommand` throws an exception instead of returning a reply — your signal to retry or fall back.

**Gotchas:** the broker can also surface a timed-out request as a general operation error rather than a dedicated timeout exception, so production code should catch broadly (`Exception`), not just `KubeMQTimeoutException`; 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; and setting the timeout too short under normal load turns transient latency into false failures.

## Prerequisites [#prerequisites]

* KubeMQ server running on `localhost:50000`
* Java SDK installed (`implementation 'io.kubemq.sdk:kubemq-sdk-Java:3.1.1'` (Gradle) or Maven dependency from [Getting Started](/sdks/java))

## Code [#code]

```java title="CommandTimeoutExample.java"
package io.kubemq.example.commands;

import io.kubemq.sdk.cq.*;

public class CommandTimeoutExample {
    private static final String ADDRESS = "localhost:50000";
    private static final String CLIENT_ID = "java-commands-command-timeout-client";
    private static final String CHANNEL = "java-commands.command-timeout";

    public static void main(String[] args) throws InterruptedException {
        // Create a client connected to the KubeMQ server
        CQClient client = CQClient.builder().address(ADDRESS).clientId(CLIENT_ID).build();
        client.ping();
        // Create the commands channel
        client.createCommandsChannel(CHANNEL);

        // Subscribe to handle commands (handler intentionally delays 3s)
        CommandsSubscription sub = CommandsSubscription.builder()
                .channel(CHANNEL)
                .onReceiveCommandCallback(cmd -> {
                    try { Thread.sleep(3000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
                    client.sendResponseMessage(CommandResponseMessage.builder()
                            .commandReceived(cmd).isExecuted(true).build());
                })
                .onErrorCallback(err -> {})
                .build();
        // Start the command handler subscription
        client.subscribeToCommands(sub);
        Thread.sleep(300);

        // Send command with short timeout (expect timeout)
        System.out.println("Sending command with 1s timeout (handler takes 3s)...");
        try {
            client.sendCommand(CommandMessage.builder()
                    .channel(CHANNEL).body("Slow command".getBytes()).timeoutInSeconds(1).build());
        } catch (Exception e) {
            System.out.println("Timeout (expected): " + e.getMessage());
        }

        // Wait for handler to finish processing the first command before sending the second
        Thread.sleep(4000);

        // Send command with sufficient timeout (expect success)
        System.out.println("\nSending command with 5s timeout (handler takes 3s)...");
        try {
            CommandResponseMessage resp = client.sendCommand(CommandMessage.builder()
                    .channel(CHANNEL).body("Normal command".getBytes()).timeoutInSeconds(5).build());
            System.out.println("Success: " + resp.isExecuted());
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
        }

        // Clean up resources
        sub.cancel();
        client.deleteCommandsChannel(CHANNEL);
        client.close();
    }
}

```

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

* `timeoutInSeconds(1)` in `CommandMessage` sets the deadline at the broker level; when no response arrives within 1 second the broker terminates the pending request and the client receives a timeout exception.
* The handler sleeps 3 seconds intentionally, guaranteeing the first command exceeds its deadline; the second command uses a 5-second timeout, which is sufficient.
* `Thread.sleep(4000)` between the two commands waits for the handler to finish processing the first (already-timed-out) command before sending the second to avoid queue depth interference.
* Catch `Exception` (not just `KubeMQTimeoutException`) in production because the broker can also return other error conditions when a deadline is exceeded.

## Related [#related]

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