{"record":{"id":"19122b3d35c965ad","repo":"apache/pulsar","slug":"interrupted-deleting-cookie-for-bookie-bookieid","errorCode":null,"errorMessage":"Interrupted deleting cookie for bookie ${bookieId}","messagePattern":"Interrupted deleting cookie for bookie (.+?)","errorType":"exception","errorClass":"BookieException.MetadataStoreException","httpStatus":null,"severity":"warning","filePath":"pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarRegistrationManager.java","lineNumber":281,"sourceCode":"            LongVersion version = new LongVersion(res.get().getStat().getVersion());\n            return new Versioned<>(res.get().getValue(), version);\n        } catch (InterruptedException ie) {\n            Thread.currentThread().interrupt();\n            throw new BookieException.MetadataStoreException(ie);\n        } catch (ExecutionException | TimeoutException e) {\n            throw new BookieException.MetadataStoreException(e);\n        }\n    }\n\n    @Override\n    public void removeCookie(BookieId bookieId, Version version) throws BookieException {\n        String path = this.cookiePath + \"/\" + bookieId;\n        try {\n            store.delete(path, Optional.of(((LongVersion) version).getLongVersion()))\n                    .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);\n        } catch (InterruptedException e) {\n            Thread.currentThread().interrupt();\n            throw new BookieException.MetadataStoreException(\"Interrupted deleting cookie for bookie \" + bookieId, e);\n        } catch (ExecutionException e) {\n            if (e.getCause() instanceof MetadataStoreException.NotFoundException) {\n                throw new BookieException.CookieNotFoundException(bookieId.toString());\n            } else {\n                throw new BookieException.MetadataStoreException(\"Failed to delete cookie for bookie \" + bookieId);\n            }\n        } catch (TimeoutException ex) {\n            throw new BookieException.MetadataStoreException(\"Failed to delete cookie for bookie \" + bookieId);\n        }\n\n        log.info().attr(\"cookiePath\", cookiePath).attr(\"bookieId\", bookieId).log(\"Removed cookie for bookie\");\n    }\n\n    @Override\n    public boolean prepareFormat() throws Exception {\n        boolean ledgerRootExists = store.exists(ledgersRootPath).get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);\n        boolean availableNodeExists = store.exists(bookieRegistrationPath).get(BLOCKING_CALL_TIMEOUT, MILLISECONDS);\n        // Create ledgers root node if not exists","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-metadata/src/main/java/org/apache/pulsar/metadata/bookkeeper/PulsarRegistrationManager.java#L263-L299","documentation":"removeCookie performs a blocking store.delete(path, expectedVersion).get(timeout) on the asynchronous MetadataStore. If the waiting thread is interrupted, the manager restores the interrupt flag and throws BookieException.MetadataStoreException('Interrupted deleting cookie for bookie <bookieId>'). This happens during cookie cleanup (bookie decommission or format) and indicates the thread was interrupted, not that the delete itself failed or the cookie is missing.","triggerScenarios":"The thread blocked in removeCookie's .get(BLOCKING_CALL_TIMEOUT, MILLISECONDS) is interrupted — typically during bookie shutdown/decommission while deleting the cookie, or a canceled admin/format task interrupting the worker thread.","commonSituations":"Decommissioning a bookie (bin/bookkeeper shell decommission) while the client/process is being shut down concurrently; MetadataStoreExpirer or format tooling run under an executor that gets shutDownNow; operator Ctrl-C during a long-running metadata-store stall.","solutions":["Respect the interrupt: stop the current decommission/cleanup task; the interrupt flag has been re-set so downstream code will also see it.","Re-run the decommission command after the environment is stable — removeCookie is safe to retry if the cookie still exists.","Fix lifecycle ordering so cookie deletion completes before the executor/process begins shutting down.","If the metadata store is stalling (which makes long blocking waits likely), resolve the store latency first, then retry."],"exampleFix":"// before\ntry {\n    regManager.removeCookie(bookieId, version);\n} catch (BookieException e) {\n    log.info(\"ignoring\", e); // swallows interrupt\n}\n\n// after\ntry {\n    regManager.removeCookie(bookieId, version);\n} catch (BookieException.MetadataStoreException e) {\n    if (Thread.currentThread().isInterrupted()) {\n        Thread.currentThread().interrupt();\n        return; // abort cleanup, retry later\n    }\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    regManager.removeCookie(bookieId, version);\n} catch (BookieException.MetadataStoreException e) {\n    if (Thread.currentThread().isInterrupted()) {\n        // abort decommission gracefully; safe to rerun later\n        return;\n    }\n    throw e;\n}","preventionTips":["Run decommission/format tasks to completion without interrupting the worker (avoid Ctrl-C and shutdownNow mid-delete).","Sequence shutdown so cookie cleanup finishes before executors are torn down.","Resolve metadata store stalls first — long blocking waits make interrupts from watchdogs likely.","removeCookie is retryable: if interrupted, rerun the decommission once stable."],"tags":["bookkeeper","metadata-store","cookie","interrupted","decommission"],"backgroundTag":"thread-interrupted","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}