diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 7381504f01083683528453d93affeec94f320a65..6c0f101cd7ebd9b86f96c669f7fdc661f6d37b26 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -269,6 +269,7 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe
 	mPixelArea(1024.f),
 	mInventory(NULL),
 	mInventorySerialNum(0),
+	mExpectedInventorySerialNum(0),
 	mInvRequestState(INVENTORY_REQUEST_STOPPED),
 	mInvRequestXFerId(0),
 	mInventoryDirty(FALSE),
@@ -2802,13 +2803,13 @@ void LLViewerObject::doUpdateInventory(
 			{
 				// best guess.
 				perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic);
-				--mInventorySerialNum;
+				--mExpectedInventorySerialNum;
 			}
 			else
 			{
 				// dummy it up.
 				perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic);
-				--mInventorySerialNum;
+				--mExpectedInventorySerialNum;
 			}
 		}
 		LLViewerInventoryItem* oldItem = item;
@@ -2816,7 +2817,11 @@ void LLViewerObject::doUpdateInventory(
 		new_item->setPermissions(perm);
 		mInventory->push_front(new_item);
 		doInventoryCallback();
-		++mInventorySerialNum;
+		++mExpectedInventorySerialNum;
+	}
+	else if (is_new)
+	{
+		++mExpectedInventorySerialNum;
 	}
 }
 
@@ -2883,7 +2888,7 @@ void LLViewerObject::moveInventory(const LLUUID& folder_id,
 		if(!item->getPermissions().allowCopyBy(gAgent.getID()))
 		{
 			deleteInventoryItem(item_id);
-			++mInventorySerialNum;
+			++mExpectedInventorySerialNum;
 		}
 	}
 }
@@ -3146,74 +3151,95 @@ S32 LLFilenameAndTask::sCount = 0;
 // static
 void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
 {
-	LLUUID task_id;
-	msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
-	LLViewerObject* object = gObjectList.findObject(task_id);
-	if(!object)
-	{
-		LL_WARNS() << "LLViewerObject::processTaskInv object "
-			<< task_id << " does not exist." << LL_ENDL;
-		return;
-	}
+    LLUUID task_id;
+    msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
+    LLViewerObject* object = gObjectList.findObject(task_id);
+    if (!object)
+    {
+        LL_WARNS() << "LLViewerObject::processTaskInv object "
+            << task_id << " does not exist." << LL_ENDL;
+        return;
+    }
 
-	LLFilenameAndTask* ft = new LLFilenameAndTask;
-	ft->mTaskID = task_id;
-	// we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
-	msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
+    LLFilenameAndTask* ft = new LLFilenameAndTask;
+    ft->mTaskID = task_id;
+    // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update
+    msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial);
 
-	if (ft->mSerial < object->mInventorySerialNum)
-	{
-		// viewer did some changes to inventory that were not saved yet.
-		LL_DEBUGS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client serial: " << object->mInventorySerialNum << LL_ENDL;
-		object->mInventorySerialNum = ft->mSerial;
-	}
+    if (ft->mSerial == object->mInventorySerialNum)
+    {
+        // Loop Protection.
+        // We received same serial twice.
+        // Viewer did some changes to inventory that couldn't be saved server side
+        // or something went wrong to cause serial to be out of sync
+        LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL;
+        object->mExpectedInventorySerialNum = ft->mSerial;
+    }
 
-	std::string unclean_filename;
-	msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
-	ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
+    if (ft->mSerial < object->mExpectedInventorySerialNum)
+    {
+        // out of date message, record to current serial for loop protection, but do not load it
+        // just drop xfer to restart on idle
+        if (ft->mSerial < object->mInventorySerialNum)
+        {
+            LL_WARNS() << "Somehow task serial decreased, out of order packet?" << LL_ENDL;
+        }
+        object->mInventorySerialNum = ft->mSerial;
+        object->mInvRequestXFerId = 0;
+        object->mInvRequestState = INVENTORY_REQUEST_STOPPED;
+    }
+    else if (ft->mSerial >= object->mExpectedInventorySerialNum)
+    {
+        object->mInventorySerialNum = ft->mSerial;
+        object->mExpectedInventorySerialNum = ft->mSerial;
 
-	if(ft->mFilename.empty())
-	{
-		LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
-		// mock up some inventory to make a drop target.
-		if(object->mInventory)
-		{
-			object->mInventory->clear(); // will deref and delete it
-		}
-		else
-		{
-			object->mInventory = new LLInventoryObject::object_list_t();
-		}
-		LLPointer<LLInventoryObject> obj;
-		obj = new LLInventoryObject(object->mID, LLUUID::null,
-									LLAssetType::AT_CATEGORY,
-									"Contents");
-		object->mInventory->push_front(obj);
-		object->doInventoryCallback();
-		delete ft;
-		return;
-	}
-	U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename), 
-								ft->mFilename, LL_PATH_CACHE,
-								object->mRegionp->getHost(),
-								TRUE,
-								&LLViewerObject::processTaskInvFile,
-								(void**)ft,
-								LLXferManager::HIGH_PRIORITY);
-	if (object->mInvRequestState == INVENTORY_XFER)
-	{
-		if (new_id > 0 && new_id != object->mInvRequestXFerId)
-		{
-			// we started new download.
-			gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
-			object->mInvRequestXFerId = new_id;
-		}
-	}
-	else
-	{
-		object->mInvRequestState = INVENTORY_XFER;
-		object->mInvRequestXFerId = new_id;
-	}
+        std::string unclean_filename;
+        msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
+        ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
+
+        if (ft->mFilename.empty())
+        {
+            LL_DEBUGS() << "Task has no inventory" << LL_ENDL;
+            // mock up some inventory to make a drop target.
+            if (object->mInventory)
+            {
+                object->mInventory->clear(); // will deref and delete it
+            }
+            else
+            {
+                object->mInventory = new LLInventoryObject::object_list_t();
+            }
+            LLPointer<LLInventoryObject> obj;
+            obj = new LLInventoryObject(object->mID, LLUUID::null,
+                LLAssetType::AT_CATEGORY,
+                "Contents");
+            object->mInventory->push_front(obj);
+            object->doInventoryCallback();
+            delete ft;
+            return;
+        }
+        U64 new_id = gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
+            ft->mFilename, LL_PATH_CACHE,
+            object->mRegionp->getHost(),
+            TRUE,
+            &LLViewerObject::processTaskInvFile,
+            (void**)ft,
+            LLXferManager::HIGH_PRIORITY);
+        if (object->mInvRequestState == INVENTORY_XFER)
+        {
+            if (new_id > 0 && new_id != object->mInvRequestXFerId)
+            {
+                // we started new download.
+                gXferManager->abortRequestById(object->mInvRequestXFerId, -1);
+                object->mInvRequestXFerId = new_id;
+            }
+        }
+        else
+        {
+            object->mInvRequestState = INVENTORY_XFER;
+            object->mInvRequestXFerId = new_id;
+        }
+    }
 }
 
 void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status)
@@ -3227,6 +3253,13 @@ void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtS
 		&& ft->mSerial >= object->mInventorySerialNum)
 	{
 		object->mInventorySerialNum = ft->mSerial;
+		LL_DEBUGS() << "Receiving inventory task file for serial " << object->mInventorySerialNum << " taskid: " << ft->mTaskID << LL_ENDL;
+		if (ft->mSerial < object->mExpectedInventorySerialNum)
+		{
+			// User managed to change something while inventory was loading
+			LL_DEBUGS() << "Processing file that is potentially out of date for task: " << ft->mTaskID << LL_ENDL;
+		}
+
 		if (object->loadTaskInvFile(ft->mFilename))
 		{
 
@@ -3376,7 +3409,7 @@ void LLViewerObject::removeInventory(const LLUUID& item_id)
 	msg->addUUIDFast(_PREHASH_ItemID, item_id);
 	msg->sendReliable(mRegionp->getHost());
 	deleteInventoryItem(item_id);
-	++mInventorySerialNum;
+	++mExpectedInventorySerialNum;
 }
 
 bool LLViewerObject::isTextureInInventory(LLViewerInventoryItem* item)
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 9aaf28f5d02c3578fd2de50e445fcf0b0c5dc99e..077b02e097543102a2ba9ad2b72e06e4e17728f1 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -802,6 +802,7 @@ class LLViewerObject
 	typedef std::list<LLInventoryCallbackInfo*> callback_list_t;
 	callback_list_t mInventoryCallbacks;
 	S16 mInventorySerialNum;
+	S16 mExpectedInventorySerialNum;
 
 	enum EInventoryRequestState
 	{