{"id":"3b052a4b6fa53733","repo":"apache/kafka","slug":"interrupted-waiting-for-results-from-fetching-reco","errorCode":null,"errorMessage":"Interrupted waiting for results from fetching records","messagePattern":"Interrupted waiting for results from fetching records","errorType":"exception","errorClass":"InterruptException","httpStatus":null,"severity":"warning","filePath":"clients/src/main/java/org/apache/kafka/clients/consumer/internals/FetchBuffer.java","lineNumber":179,"sourceCode":"     * </ol>\n     *\n     * @param timer Timer that provides time to wait\n     */\n    void awaitWakeup(Timer timer) {\n        try {\n            lock.lock();\n\n            while (!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 the thread was interrupted before we start waiting, it still counts as\n                    // interrupted from the point of view of the KafkaConsumer.poll(Duration) contract.\n                    // We only need to check this when we are not going to wait because waiting\n                    // already checks whether the thread is interrupted.\n                    if (Thread.interrupted())\n                        throw new InterruptException(\"Interrupted waiting for results from fetching records\");\n\n                    break;\n                }\n\n                if (!blockingCondition.await(timer.remainingMs(), TimeUnit.MILLISECONDS)) {\n                    break;\n                }\n            }\n        } catch (InterruptedException e) {\n            throw new InterruptException(\"Interrupted waiting for results from fetching records\", e);\n        } finally {\n            lock.unlock();\n            timer.update();\n        }\n    }\n\n    void wakeup() {\n        try {","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/clients/consumer/internals/FetchBuffer.java#L161-L197","documentation":"InterruptException thrown inside FetchBuffer.awaitWakeup when the consumer thread's interrupted flag is found set at the moment the timer expired (before entering the await). Per the KafkaConsumer.poll(Duration) contract, an interrupt observed even when not blocking counts as an interruption of the fetch wait. No cause exception is attached because Thread.interrupted() only returns a boolean.","triggerScenarios":"Thread.interrupt() called on the consumer thread and the awaitWakeup timer is already expired when the check at FetchBuffer.java:178 runs (so the code takes the expiry branch rather than the await branch).","commonSituations":"Application shuts down the consumer thread via interrupt while poll()'s remaining time has already elapsed; executor shutdownNow() racing with a poll nearing its timeout; wakeup() not used and interrupt lands at the boundary of the timer.","solutions":["Prefer KafkaConsumer.wakeup() for cooperative shutdown; it sets the wokenup flag and avoids the interrupt path.","If interrupts are expected, catch InterruptException around poll() and restore the interrupt flag before exiting.","Avoid very short poll(Duration) values that cause the timer to expire before the await check."],"exampleFix":"// before\nconsumerThread.interrupt();\n\n// after\ntry {\n  while (running) consumer.poll(Duration.ofMillis(500));\n} catch (InterruptException | WakeupException e) {\n  Thread.currentThread().interrupt();\n} finally { consumer.close(); }","handlingStrategy":"try-catch","validationCode":"// Same call path as [171]: cannot pre-validate an interrupt. But you can avoid the\n// race where the thread was interrupted BEFORE entering awaitWakeup by clearing the\n// flag intentionally only at a known checkpoint:\nif (Thread.currentThread().isInterrupted() && shutdownRequested) {\n    // exit cleanly instead of letting FetchBuffer.awaitWakeup throw at line 179\n    return;\n}","typeGuard":null,"tryCatchPattern":"try {\n    consumer.poll(Duration.ofMillis(Long.MAX_VALUE)); // long poll, hits awaitWakeup\n} catch (org.apache.kafka.common.errors.InterruptException e) {\n    // Thrown at FetchBuffer.java:179 when Thread.interrupted() is true on entry to\n    // the wait path (timer already expired). It is a shutdown signal.\n    Thread.currentThread().interrupt();\n    log.debug(\"Consumer poll interrupted on entry; shutting down\");\n    return;\n}","preventionTips":["Prefer consumer.wakeup() to Thread.interrupt() to break a long poll — wakeup uses an internal flag, not the JDK interrupt, and avoids this path entirely.","If you must interrupt, do it from a dedicated shutdown hook and treat InterruptException as terminal.","Restore the interrupt flag in the catch so executors/thread pools observe the interrupt.","Do not call interrupt() for non-shutdown reasons (e.g., timeouts) — use poll(Duration) with a short timeout instead."],"tags":["consumer","interrupt","poll","shutdown"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}