diff --git a/src/Quasar/Wayland/Protocol/TH.hs b/src/Quasar/Wayland/Protocol/TH.hs
index 2dc7475cff662e44ea2c8e991cbfa35335147a57..10f6410dbecf0d56b500503700cb137b609ff1c9 100644
--- a/src/Quasar/Wayland/Protocol/TH.hs
+++ b/src/Quasar/Wayland/Protocol/TH.hs
@@ -617,7 +617,9 @@ parseMessage _isRequest interface (opcode, element) = do
 
   isDestructor <-
     case mtype of
-      Nothing -> pure False
+      -- Patch `wl_callback.done` to be a destructor.
+      -- This ensures `done` is called only once, releases the id, and prevents a memory leak.
+      Nothing -> pure (interface == "wl_callback" && name == "done")
       Just "destructor" -> pure True
       Just messageType -> fail $ "Unknown message type: " <> messageType