{"id":"be89c7f1927cce73","repo":"apache/kafka","slug":"interrupted-waiting-for-results-for-application-ev","errorCode":null,"errorMessage":"Interrupted waiting for results for application event ${event}","messagePattern":"Interrupted waiting for results for application event (.+?)","errorType":"exception","errorClass":"InterruptException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/internals/events/ApplicationEventHandler.java","lineNumber":145,"sourceCode":"     * Add a {@link CompletableApplicationEvent} to the handler. The method blocks waiting for the result, and will\n     * return the result value upon successful completion; otherwise throws an error.\n     *\n     * <p/>\n     *\n     * See {@link ConsumerUtils#getResult(Future)} for more details.\n     *\n     * @param event A {@link CompletableApplicationEvent} created by the polling thread\n     * @return      Value that is the result of the event\n     * @param <T>   Type of return value of the event\n     */\n    public <T> T addAndGet(final CompletableApplicationEvent<T> event) {\n        Objects.requireNonNull(event, \"CompletableApplicationEvent provided to addAndGet must be non-null\");\n        add(event);\n        // Check if the thread was interrupted before we start waiting, to ensure that we\n        // propagate the exception even if we end up not having to wait (the event could complete\n        // between the time it's added and the time we attempt to getResult)\n        if (Thread.interrupted()) {\n            throw new InterruptException(\"Interrupted waiting for results for application event \" + event);\n        }\n        return ConsumerUtils.getResult(event.future());\n    }\n\n    @Override\n    public void close() {\n        close(Duration.ZERO);\n    }\n\n    public void close(final Duration timeout) {\n        closer.close(\n                () -> Utils.closeQuietly(() -> networkThread.close(timeout), \"consumer network thread\"),\n                () -> log.warn(\"The application event handler was already closed\")\n        );\n    }\n\n    /**\n     * Best-effort check that the consumer network thread is still alive. If the thread has","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/events/ApplicationEventHandler.java#L127-L163","documentation":"Thrown as InterruptException (a KafkaException subtype) by ApplicationEventHandler.addAndGet when Thread.interrupted() returns true after the event has been added to the network-thread queue but before getResult blocks. It is a pre-wait interrupt check: the client surfaces a pending interrupt immediately instead of letting it surface later inside the blocking future.get(). This is the async-consumer application-thread → network-thread bridge.","triggerScenarios":"The application thread calling the consumer is interrupted (Thread.interrupt()) while invoking any blocking consumer API that goes through addAndGet (e.g. committed, partitionsFor, listTopics, position, offsets-for-times, beginning/end offsets in the new async consumer). The interrupt flag was set before the consumer had a chance to block on the future.","commonSituations":"Application frameworks that interrupt worker threads on shutdown (Spring @PreDestroy, executor.shutdownNow(), servlet container unload); timeouts implemented via Thread.interrupt() rather than the consumer's own API timeouts; a parent thread canceling a task that wraps a consumer call; mixed use of the consumer inside a ForkJoinPool whose tasks get cancelled.","solutions":["Stop interrupting the consumer thread — prefer consumer.close(duration) and the consumer's own poll/request timeouts for cancellation.","If interrupts are expected (shutdown), catch InterruptException, restore the interrupt flag (Thread.currentThread().interrupt()), and exit cleanly.","Avoid sharing a consumer across threads; own it on a single thread so interrupts come from your own lifecycle code."],"exampleFix":"// before\nexecutor.shutdownNow(); // sends Thread.interrupt() to the polling thread\n\n// after\nconsumer.wakeup();\nexecutor.shutdown();\nawaitTermination(executor, Duration.ofSeconds(30));\n// inside the consumer loop:\ntry {\n    ConsumerRecords<?,?> recs = consumer.poll(Duration.ofMillis(500));\n} catch (InterruptException | WakeupException e) {\n    Thread.currentThread().interrupt();\n    return; // graceful shutdown\n}","handlingStrategy":"try-catch","validationCode":"// Avoid interrupting the consumer thread from outside; signal shutdown via a flag and close().\nprivate volatile boolean running = true;\n// in the consumer loop:\nwhile (running) { consumer.poll(Duration.ofMillis(500)); }\n// shutdown path: running=false; consumer.wakeup();  -- do NOT Thread.interrupt() the consumer thread","typeGuard":"import org.apache.kafka.common.errors.InterruptException;\n\n/** True iff a throwable is Kafka's InterruptException wrapper around thread interruption. */\nstatic boolean isKafkaInterrupt(Throwable t) {\n    return t instanceof InterruptException;\n}","tryCatchPattern":"try {\n    consumer.poll(Duration.ofMillis(1000));\n} catch (org.apache.kafka.common.errors.InterruptException e) {\n    // Honor the interrupt: restore the flag so callers up the stack see it.\n    Thread.currentThread().interrupt();\n    // then exit the loop cleanly — do not swallow\n    running = false;\n}","preventionTips":["Never call Thread.interrupt() on the consumer thread; use consumer.wakeup() for cooperative shutdown.","In shutdown hooks, set a stop flag and wakeup() — don't interrupt from a signal handler.","If you must catch InterruptException, always re-set the interrupt status via Thread.currentThread().interrupt().","Close the consumer (KafkaConsumer.close(timeout)) in a finally block to release the network thread cleanly."],"tags":["kafka","consumer","async","interrupt","threading","shutdown","application-event"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}