diff --git a/src/upnp/protocol/mapping.cpp b/src/upnp/protocol/mapping.cpp
index 6e47ae6d11eb07cd8075c0e93b85b4547a6a64fd..f5c0516811d34533055cbc053f1798d604b5dc1e 100644
--- a/src/upnp/protocol/mapping.cpp
+++ b/src/upnp/protocol/mapping.cpp
@@ -299,6 +299,8 @@ Mapping::notify(sharedPtr_t mapping)
     NotifyCallback cb;
     {
         std::lock_guard lock(mapping->mutex_);
+        if (!mapping->notifyCb_)
+            return;
         if (mapping->state_ != mapping->lastNotifiedState_) {
             mapping->lastNotifiedState_ = mapping->state_;
             cb = mapping->notifyCb_;
@@ -320,6 +322,13 @@ Mapping::setNotifyCallback(NotifyCallback cb)
 {
     std::lock_guard lock(mutex_);
     notifyCb_ = std::move(cb);
+    if (!notifyCb_) {
+        // When a mapping is released by a controller, its NotifyCallback is set
+        // to null (see UPnPContext::releaseMapping). We need to reset
+        // lastNotifiedState_ when this happens to make sure the mapping isn't
+        // in a incorrect state if it's later reused by a different controller.
+        lastNotifiedState_ = std::nullopt;
+    }
 }
 
 void