apache/kafka · info · TimeoutException
TimeoutExceptions are successfully injected for test.
Error message
TimeoutExceptions are successfully injected for test.
What it means
Thrown by MockProducer.clientInstanceId(Duration) as a TimeoutException (note: success-path signalling) when the test has armed timeout injection via injectTimeoutException(int). Each call to clientInstanceId() decrements the counter (or stays infinite for -1) and throws this exception until the counter reaches zero. It lets tests deterministically simulate broker telemetry timeouts without a real network.
Source
Thrown at clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java:448
*/
public void setClientInstanceId(final Uuid instanceId) {
clientInstanceId = instanceId;
}
@Override
public Uuid clientInstanceId(Duration timeout) {
if (telemetryDisabled) {
throw new IllegalStateException();
}
if (clientInstanceId == null) {
throw new UnsupportedOperationException("clientInstanceId not set");
}
if (injectTimeoutExceptionCounter != 0) {
// -1 is used as "infinite"
if (injectTimeoutExceptionCounter > 0) {
--injectTimeoutExceptionCounter;
}
throw new TimeoutException("TimeoutExceptions are successfully injected for test.");
}
return clientInstanceId;
}
public Map<MetricName, Metric> metrics() {
return mockMetrics;
}
/**
* Set a mock metric for testing purpose
*/
public void setMockMetrics(MetricName name, Metric metric) {
mockMetrics.put(name, metric);
}
@Override
public void close() {View on GitHub (pinned to c31c9215e1)
Solutions
- Call injectTimeoutException(0) (or create a fresh MockProducer) once you want clientInstanceId() to return normally again.
- In the test, drive the expected number of timeout retries then assert the call succeeds on the next attempt.
- Do not use -1 (infinite) unless the test specifically checks unbounded retries; prefer an exact count.
- If this exception reaches production-looking code in a test, confirm the production retry/backoff logic calls close() and exits after exhausting retries instead of looping forever.
Example fix
// before
producer.injectTimeoutException(3);
Uuid id = producer.clientInstanceId(Duration.ofSeconds(1)); // TimeoutException x3
// after
producer.injectTimeoutException(3);
for (int i = 0; i < 3; i++) {
try { producer.clientInstanceId(Duration.ofSeconds(1)); }
catch (TimeoutException expected) { /* retry */ }
}
Uuid id = producer.clientInstanceId(Duration.ofSeconds(1)); // now returns Defensive patterns
Strategy: retry
Validate before calling
// Before calling clientInstanceId(), check the injected-timeout counter
// state if your test exposes it; otherwise just retry with backoff.
// Typical defensive wrapper:
Uuid getClientInstanceIdWithRetry(MockProducer<?,?> p, Duration perTry, int maxAttempts) {
RuntimeException last = null;
for (int i = 0; i < maxAttempts; i++) {
try {
return p.clientInstanceId(perTry);
} catch (org.apache.kafka.common.errors.TimeoutException te) {
last = te;
// backoff before next attempt
}
}
throw last;
} Prevention
- Treat injected TimeoutException as transient — retry with bounded attempts and backoff.
- If you injected timeouts via injectTimeoutException(counter), set the counter to the exact finite number your test tolerates, not -1 (infinite).
- Reset the counter (set to 0) once the test scenario is over so unrelated calls don't time out.
- Cap total retry time so an accidentally-infinite counter can't hang the test.
When it happens
Trigger: Calling producer.clientInstanceId(timeout) after producer.injectTimeoutException(n) with n>0 or n=-1. The throw at line 448 occurs only when telemetry is not disabled and clientInstanceId is already set (otherwise the earlier guards fire). Counter is decremented at line 446.
Common situations: A test asserting that the application retries clientInstanceId() after a timeout; setting injectTimeoutException(-1) (infinite) and forgetting to reset it, so subsequent tests on the same instance never succeed; a test expecting the value but the injection was left armed from a previous case.
Related errors
- clientInstanceId not set
- Timeout needs to be greater than 0
- The specified value of default.api.timeout.ms must be no sma
- The timeout cannot be negative.
- Timeout of {}ms expired before the position for partition {}
AI-assisted analysis of apache/kafka@c31c9215e1 (2026-08-03).
Data as JSON: /data/errors/d15b666fd40095c6.json.
Report an issue: GitHub.