{"record":{"id":"bb598f7674a3012f","repo":"NationalSecurityAgency/ghidra","slug":"private-queue-no-longer-exists","errorCode":null,"errorMessage":"Private queue no longer exists","messagePattern":"Private queue no longer exists","errorType":"exception","errorClass":"NoSuchElementException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/framework/data/DomainObjectEventQueues.java","lineNumber":106,"sourceCode":"\t\tDomainObjectChangeSupport docs = new DomainObjectChangeSupport(source, maxDelay, lock);\n\t\tdocs.addListener(listener);\n\t\tprivateEventQueues.put(id, new PrivateQueue(docs));\n\t\treturn id;\n\t}\n\n\tpublic boolean removePrivateEventQueue(EventQueueID id) {\n\t\tPrivateQueue privateQueue = privateEventQueues.remove(id);\n\t\tif (privateQueue == null) {\n\t\t\treturn false;\n\t\t}\n\t\tprivateQueue.cleanable.clean();\n\t\treturn true;\n\t}\n\n\tpublic void flushPrivateEventQueue(EventQueueID id) {\n\t\tPrivateQueue privateQueue = privateEventQueues.get(id);\n\t\tif (privateQueue == null) {\n\t\t\tthrow new NoSuchElementException(\"Private queue no longer exists\");\n\t\t}\n\t\tprivateQueue.flush();\n\t}\n\n\tpublic void fireEvent(DomainObjectChangeRecord ev) {\n\t\tif (eventsEnabled) {\n\t\t\teventQueue.fireEvent(ev);\n\t\t\tfor (PrivateQueue privateQueue : privateEventQueues.values()) {\n\t\t\t\tprivateQueue.fireEvent(ev);\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic void setEventsEnabled(boolean eventsEnabled) {\n\t\tif (this.eventsEnabled == eventsEnabled) {\n\t\t\treturn;\n\t\t}\n\t\tthis.eventsEnabled = eventsEnabled;","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/framework/data/DomainObjectEventQueues.java#L88-L124","documentation":"Raised as java.util.NoSuchElementException by DomainObjectEventQueues.flushPrivateEventQueue() when the given EventQueueID is not present in the privateEventQueues map. Private queues are created and removed explicitly; once removePrivateEventQueue(id) has run (or the queue was never created), flushing that id is invalid. This is the Java side of Ghidra's domain-object event system, not the Python trace client.","triggerScenarios":"Calling flushPrivateEventQueue(id) after removePrivateEventQueue(id) for the same id; flushing an id that was never registered; a double-dispose path that removes then flushes.","commonSituations":"Plugin/component disposal ordering bugs where a queue is removed before a pending flush; race between dispose and an event flush; re-entrant close logic.","solutions":["Track queue lifecycle so flush always precedes remove for a given id.","Guard the flush: check removePrivateEventQueue's return value / call getPrivateEventQueue first, or catch NoSuchElementException.","Ensure dispose paths remove a queue exactly once and do not flush afterwards."],"exampleFix":"// before\nqueues.removePrivateEventQueue(id);\nqueues.flushPrivateEventQueue(id);  // throws\n// after\nqueues.flushPrivateEventQueue(id);\nqueues.removePrivateEventQueue(id);","handlingStrategy":"validation","validationCode":"if (!queues.getPrivateEventQueue(id).isPresent()) { /* or track ids */ throw new IllegalStateException(\"queue gone\"); }","typeGuard":null,"tryCatchPattern":"try {\n    queues.flushPrivateEventQueue(id);\n} catch (NoSuchElementException e) {\n    // queue already removed; nothing to flush\n}","preventionTips":["Always flush before remove for a given EventQueueID.","Remove each queue exactly once; guard dispose ordering."],"tags":["lifecycle","events","java","domain-object","concurrency"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}