{"id":"d15b666fd40095c6","repo":"apache/kafka","slug":"timeoutexceptions-are-successfully-injected-for-te","errorCode":null,"errorMessage":"TimeoutExceptions are successfully injected for test.","messagePattern":"TimeoutExceptions are successfully injected for test\\.","errorType":"exception","errorClass":"TimeoutException","httpStatus":null,"severity":"info","filePath":"clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java","lineNumber":448,"sourceCode":"     */\n    public void setClientInstanceId(final Uuid instanceId) {\n        clientInstanceId = instanceId;\n    }\n\n    @Override\n    public Uuid clientInstanceId(Duration timeout) {\n        if (telemetryDisabled) {\n            throw new IllegalStateException();\n        }\n        if (clientInstanceId == null) {\n            throw new UnsupportedOperationException(\"clientInstanceId not set\");\n        }\n        if (injectTimeoutExceptionCounter != 0) {\n            // -1 is used as \"infinite\"\n            if (injectTimeoutExceptionCounter > 0) {\n                --injectTimeoutExceptionCounter;\n            }\n            throw new TimeoutException(\"TimeoutExceptions are successfully injected for test.\");\n        }\n\n        return clientInstanceId;\n    }\n\n    public Map<MetricName, Metric> metrics() {\n        return mockMetrics;\n    }\n\n    /**\n     * Set a mock metric for testing purpose\n     */\n    public void setMockMetrics(MetricName name, Metric metric) {\n        mockMetrics.put(name, metric);\n    }\n\n    @Override\n    public void close() {","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/producer/MockProducer.java#L430-L466","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nproducer.injectTimeoutException(3);\nUuid id = producer.clientInstanceId(Duration.ofSeconds(1)); // TimeoutException x3\n\n// after\nproducer.injectTimeoutException(3);\nfor (int i = 0; i < 3; i++) {\n    try { producer.clientInstanceId(Duration.ofSeconds(1)); }\n    catch (TimeoutException expected) { /* retry */ }\n}\nUuid id = producer.clientInstanceId(Duration.ofSeconds(1)); // now returns","handlingStrategy":"retry","validationCode":"// Before calling clientInstanceId(), check the injected-timeout counter\n// state if your test exposes it; otherwise just retry with backoff.\n// Typical defensive wrapper:\nUuid getClientInstanceIdWithRetry(MockProducer<?,?> p, Duration perTry, int maxAttempts) {\n    RuntimeException last = null;\n    for (int i = 0; i < maxAttempts; i++) {\n        try {\n            return p.clientInstanceId(perTry);\n        } catch (org.apache.kafka.common.errors.TimeoutException te) {\n            last = te;\n            // backoff before next attempt\n        }\n    }\n    throw last;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["mock-producer","telemetry","timeout","test-injection"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}