diff --git a/src/GameLogic/Player.cs b/src/GameLogic/Player.cs
index a7f316e..6e55ec8 100644
--- a/src/GameLogic/Player.cs
+++ b/src/GameLogic/Player.cs
@@ -1917,6 +1917,14 @@ public class Player : AsyncDisposable, IBucketMapObserver, IAttackable, IAttacke
/// save fails too, so the whole session is lost on relog. Serializing the packet handler funnel
/// and the save against each other closes that window. The lock is re-entrant per asynchronous
/// flow, so an inline save inside an already-serialized handler does not deadlock.
+ ///
+ /// Invariant: never acquire another player's persistence lock (via their
+ /// or ) from inside a
+ /// packet handler, which already holds this player's lock, unless a global lock order is enforced.
+ /// Today only the trade accept does a cross-player save, and it cannot form a cycle because a trade
+ /// has a single accepting side (so the A-then-B acquisition order has no concurrent B-then-A
+ /// counterpart). A second cross-player caller with the opposite order could deadlock.
+ ///
///
/// The result type of the operation.
/// The operation to run exclusively.