{"id":"105a9476ab9221d3","repo":"apache/kafka","slug":"thread-interrupted","errorCode":null,"errorMessage":"Thread interrupted.","messagePattern":"Thread interrupted\\.","errorType":"exception","errorClass":"InterruptException","httpStatus":null,"severity":"warning","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/internals/ShareFetchBuffer.java","lineNumber":154,"sourceCode":"     * <ol>\n     *     <li>The buffer was already non-empty on entry</li>\n     *     <li>The buffer was populated during the wait</li>\n     *     <li>The remaining time on the {@link Timer timer} elapsed</li>\n     *     <li>The thread was interrupted</li>\n     * </ol>\n     *\n     * @param timer Timer that provides time to wait\n     */\n    void awaitNotEmpty(Timer timer) {\n        lock.lock();\n        try {\n            while (completedFetches.isEmpty() && !wokenUp.compareAndSet(true, false)) {\n                // Update the timer before we head into the loop in case it took a while to get the lock.\n                timer.update();\n\n                if (timer.isExpired()) {\n                    if (Thread.interrupted())\n                        throw new InterruptException(\"Thread interrupted.\");\n                    break;\n                }\n\n                if (!notEmptyCondition.await(timer.remainingMs(), TimeUnit.MILLISECONDS)) {\n                    break;\n                }\n            }\n        } catch (InterruptedException e) {\n            throw new InterruptException(\"Timeout waiting for results from fetching records\", e);\n        } finally {\n            lock.unlock();\n            timer.update();\n        }\n    }\n\n    void wakeup() {\n        wokenUp.set(true);\n        lock.lock();","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/ShareFetchBuffer.java#L136-L172","documentation":"Thrown by ShareFetchBuffer.awaitNotEmpty when the thread's interrupt status is found set at the moment the fetch timer expires. The share consumer interprets an interrupted thread as a request to abort the blocking wait for records; it surfaces the interrupt as Kafka's InterruptException so callers can handle thread cancellation cleanly rather than returning empty data.","triggerScenarios":"The application thread calling consumer.poll(...) is interrupted (Thread.interrupt()) by a parent executor, shutdown hook, or CompletableFuture cancellation while the share consumer is blocked in awaitNotEmpty waiting for records to arrive.","commonSituations":"Shutting down an ExecutorService that owns the consumer thread; cancelling a task wrapped around poll(); Spring/@PreDestroy or container shutdown interrupting worker threads; using Future.cancel(true) on a polling task.","solutions":["Catch InterruptException around poll() and treat it as a shutdown signal, then close the consumer and exit the run loop.","Avoid calling Thread.interrupt() on the consumer thread if you want poll() to complete; use wakeup() / close() instead to stop the share consumer cooperatively.","If using an ExecutorService, call shutdown() / shutdownNow() deliberately and propagate the interrupt status after cleanup.","Reset the interrupt flag (Thread.currentThread().interrupt()) if you must continue, then re-poll with a fresh timer."],"exampleFix":"// before\nFuture<?> f = exec.submit(() -> {\n    while (running) consumer.poll(Duration.ofSeconds(5));\n});\nf.cancel(true);  // interrupts mid-poll -> InterruptException\n\n// after\nFuture<?> f = exec.submit(() -> {\n    try {\n        while (running) consumer.poll(Duration.ofSeconds(5));\n    } catch (InterruptException | WakeupException e) {\n        // graceful shutdown\n    } finally {\n        consumer.close();\n    }\n});\nconsumer.wakeup();  // cooperative stop instead of cancel(true)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    consumer.poll(Duration.ofSeconds(30));\n} catch (org.apache.kafka.common.errors.InterruptException e) {\n    // The consumer thread was interrupted (e.g. shutdown). Restore the interrupt status\n    // so upper layers can observe it, then exit the loop cleanly.\n    Thread.currentThread().interrupt();\n    log.info(\"Consumer poll interrupted, shutting down\");\n    return ConsumerPollOutcome.SHUTDOWN;\n} finally {\n    consumer.close();\n}","preventionTips":["Always re-assert the interrupt flag in the catch block (Thread.currentThread().interrupt()).","Drive shutdown via a single AtomicBoolean flag plus consumer.wakeup(), not via Thread.interrupt() alone.","Make sure close() is called from a finally block so the network thread is released."],"tags":["share-consumer","threading","interrupt","kafka-client"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}