{"record":{"id":"ae8d84b173ae2cc6","repo":"pinpoint-apm/pinpoint","slug":"scantask-interrupted","errorCode":null,"errorMessage":"ScanTask Interrupted","messagePattern":"ScanTask Interrupted","errorType":"exception","errorClass":"InterruptedIOException","httpStatus":null,"severity":"warning","filePath":"commons-hbase/src/main/java/com/navercorp/pinpoint/common/hbase/parallel/ScanTask.java","lineNumber":134,"sourceCode":"            return new DistributedScanner(saltKeySize, scanners);\n        }\n    }\n\n    @Override\n    public Result next() throws IOException {\n        if (this.isQueueClosed) {\n            return null;\n        }\n        if (localBuffer != null) {\n            return localBuffer;\n        }\n        Result take = null;\n        try {\n            take = this.resultQueue.take();\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            isDone = true;\n            throw new InterruptedIOException(\"ScanTask Interrupted\");\n        }\n        if (take == END_RESULT) {\n            this.isQueueClosed = true;\n            localBuffer = null;\n            return null;\n        }\n        localBuffer = take;\n        return localBuffer;\n    }\n\n    @Override\n    public void consume() {\n        localBuffer = null;\n    }\n\n    @Override\n    public boolean isExhausted() {\n        return this.isQueueClosed;","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/commons-hbase/src/main/java/com/navercorp/pinpoint/common/hbase/parallel/ScanTask.java#L116-L152","documentation":"ScanTask.next blocks on its internal resultQueue; if the waiting thread is interrupted it restores the interrupt flag, marks the task done, and throws InterruptedIOException('ScanTask Interrupted'). This propagates shutdown/cancellation to the parallel-scanner consumer instead of silently dropping rows.","triggerScenarios":"Thread interruption while blocked on resultQueue.take() — typically executor shutdown, application shutdown, or a timeout path that interrupts the scanning thread during a parallel HBase scan iteration.","commonSituations":"Graceful shutdown of pinpoint web/collector mid-scan; Future.cancel(true) on scan tasks; container/deploys killing threads; timeouts interrupting long-running distributed scans.","solutions":["Ensure the application doesn't interrupt scan threads prematurely (check shutdown hooks and Future.cancel(true) usage)","Increase scan/operation timeouts so slow scans complete without being cancelled","Retry the scan after an interruption if it was spurious, on a non-interrupted executor","Catch InterruptedIOException in the consumer and treat it as a cancelled scan, re-checking Thread.currentThread().isInterrupted()"],"exampleFix":"// before\ntry { while ((r = scanTask.next()) != null) {} } catch (InterruptedIOException e) { /* ignored */ }\n// after\ntry { while ((r = scanTask.next()) != null) {} }\ncatch (InterruptedIOException e) {\n    logger.warn(\"Scan cancelled, retrying\", e);\n    retryScan();\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    while ((result = scanTask.next()) != null) { consume(result); }\n} catch (InterruptedIOException e) {\n    Thread.currentThread().interrupt(); // preserve cancel signal\n    throw new ScanCancelledException(e);\n}","preventionTips":["Avoid Future.cancel(true) on in-progress scans unless cancellation is intended","Ensure executor shutdown waits for scans (awaitTermination) where possible","Set realistic scan timeouts for large regions","Handle interruption cleanly on shutdown paths so scans can resume/retry"],"tags":["hbase","interruption","scan","shutdown"],"backgroundTag":"request-timeout","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}