 			if (!listenerBoxes.length)
 			{
 				listenerBoxes[0] = listenerBox;
+				if (once) onceListeners[listener] = true;
 				return;
 			}
 			
-			// Don't add the same listener twice.
-			if (indexOfListener(listener) >= 0)
+			var prevListenerIndex:int = indexOfListener(listener);
+			if (prevListenerIndex >= 0)
+			{
+				// If the listener was previously added, definitely don't add it again.
+				// But throw an exception in some cases, as the error messages explain.
+				if (onceListeners[listener] && !once)
+				{
+					throw new IllegalOperationError('You cannot addOnce() then add() the same listener without removing the relationship first.');
+				}
+				else if (!onceListeners[listener] && once)
+				{
+					throw new IllegalOperationError('You cannot add() then addOnce() the same listener without removing the relationship first.');
+				}
+				// Listener was already added, so do nothing.
 				return;
+			}
 			
 			// Assume the listeners are already sorted by priority
 			// and insert in the right spot. For listeners with the same priority,

			}
		}
		
		protected function registerListener(listener:Function, priority:int):void
		{
			// function.length is the number of arguments.
			if (listener.length < _valueClasses.length)

		//TODO: @throws
		public function add(listener:Function, priority:int = 0):void
		{
			registerListener(listener, false, priority);
		}
		
		/** @inheritDoc */
		public function addOnce(listener:Function, priority:int = 0):void
		{
			registerListener(listener, true, priority);
		}
		
		/** @inheritDoc */
