diff --git a/doc/changes/state_trackers/mr.359.3.md b/doc/changes/state_trackers/mr.359.3.md
new file mode 100644
index 000000000..b5baae0b2
--- /dev/null
+++ b/doc/changes/state_trackers/mr.359.3.md
@@ -0,0 +1,3 @@
+OpenXR: When a `XrSession` is destroyed purge the event queue of any events that
+references to it so that no events gets delivered to the applications with
+stales handles.
diff --git a/src/xrt/state_trackers/oxr/oxr_event.c b/src/xrt/state_trackers/oxr/oxr_event.c
index 3b2f80234..759a1785d 100644
--- a/src/xrt/state_trackers/oxr/oxr_event.c
+++ b/src/xrt/state_trackers/oxr/oxr_event.c
@@ -133,6 +133,44 @@ oxr_event_push_XrEventDataSessionStateChanged(struct oxr_logger *log,
 	return XR_SUCCESS;
 }
 
+XrResult
+oxr_event_remove_session_events(struct oxr_logger *log,
+                                struct oxr_session *sess)
+{
+	struct oxr_instance *inst = sess->sys->inst;
+	XrSession session = oxr_session_to_openxr(sess);
+
+	lock(inst);
+
+	struct oxr_event *e = inst->next_event;
+	while (e != NULL) {
+		struct oxr_event *cur = e;
+		e = e->next;
+
+		XrEventDataSessionStateChanged *changed = oxr_event_extra(cur);
+		if (changed->type != XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) {
+			continue;
+		}
+
+		if (changed->session != session) {
+			continue;
+		}
+
+		if (cur == inst->next_event) {
+			inst->next_event = cur->next;
+		}
+
+		if (cur == inst->last_event) {
+			inst->last_event = NULL;
+		}
+		free(cur);
+	}
+
+	unlock(inst);
+
+	return XR_SUCCESS;
+}
+
 XrResult
 oxr_poll_event(struct oxr_logger *log,
                struct oxr_instance *inst,
diff --git a/src/xrt/state_trackers/oxr/oxr_objects.h b/src/xrt/state_trackers/oxr/oxr_objects.h
index e4a8c04f0..17e6dd941 100644
--- a/src/xrt/state_trackers/oxr/oxr_objects.h
+++ b/src/xrt/state_trackers/oxr/oxr_objects.h
@@ -692,6 +692,13 @@ oxr_event_push_XrEventDataSessionStateChanged(struct oxr_logger *log,
                                               XrSessionState state,
                                               XrTime time);
 
+/*!
+ * This clears all pending events refers to the given session.
+ */
+XrResult
+oxr_event_remove_session_events(struct oxr_logger *log,
+                                struct oxr_session *sess);
+
 
 /*
  *
diff --git a/src/xrt/state_trackers/oxr/oxr_session.c b/src/xrt/state_trackers/oxr/oxr_session.c
index 11e6dae16..a1d5b7c25 100644
--- a/src/xrt/state_trackers/oxr/oxr_session.c
+++ b/src/xrt/state_trackers/oxr/oxr_session.c
@@ -840,6 +840,8 @@ oxr_session_destroy(struct oxr_logger *log, struct oxr_handle_base *hb)
 {
 	struct oxr_session *sess = (struct oxr_session *)hb;
 
+	XrResult ret = oxr_event_remove_session_events(log, sess);
+
 	// Does a null-ptr check.
 	xrt_comp_destroy(&sess->compositor);
 
@@ -848,7 +850,7 @@ oxr_session_destroy(struct oxr_logger *log, struct oxr_handle_base *hb)
 
 	free(sess);
 
-	return XR_SUCCESS;
+	return ret;
 }
 
 #define OXR_SESSION_ALLOCATE(LOG, SYS, OUT)                                    \