diff --git a/indra/newview/llaisapi.cpp b/indra/newview/llaisapi.cpp
index 4ac2acf1d11b6b9c58bb77488916d8a54e079d14..f3799361db069ea0201adf29b041ad2b0fb8e11a 100644
--- a/indra/newview/llaisapi.cpp
+++ b/indra/newview/llaisapi.cpp
@@ -709,6 +709,40 @@ void AISAPI::FetchCOF(completion_t callback)
     EnqueueAISCommand("FetchCOF", proc);
 }
 
+void AISAPI::FetchCategoryLinks(const LLUUID &catId, completion_t callback)
+{
+    std::string cap = getInvCap();
+    if (cap.empty())
+    {
+        LL_WARNS("Inventory") << "Inventory cap not found!" << LL_ENDL;
+        if (callback)
+        {
+            callback(LLUUID::null);
+        }
+        return;
+    }
+    std::string url = cap + std::string("/category/") + catId.asString() + "/links";
+
+    invokationFn_t getFn = boost::bind(
+        // Humans ignore next line.  It is just a cast to specify which LLCoreHttpUtil::HttpCoroutineAdapter routine overload.
+        static_cast<LLSD (LLCoreHttpUtil::HttpCoroutineAdapter::*)(LLCore::HttpRequest::ptr_t, const std::string &,
+                                                                   LLCore::HttpOptions::ptr_t, LLCore::HttpHeaders::ptr_t)>
+        //----
+        // _1 -> httpAdapter
+        // _2 -> httpRequest
+        // _3 -> url
+        // _4 -> body
+        // _5 -> httpOptions
+        // _6 -> httpHeaders
+        (&LLCoreHttpUtil::HttpCoroutineAdapter::getAndSuspend),
+        _1, _2, _3, _5, _6);
+
+    LLCoprocedureManager::CoProcedure_t proc(
+        boost::bind(&AISAPI::InvokeAISCommandCoro, _1, getFn, url, LLUUID::null, LLSD(), callback, FETCHCATEGORYLINKS));
+
+    EnqueueAISCommand("FetchCategoryLinks", proc);
+}
+
 /*static*/
 void AISAPI::FetchOrphans(completion_t callback)
 {
@@ -938,6 +972,7 @@ void AISAPI::InvokeAISCommandCoro(LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t ht
         case FETCHCATEGORYCATEGORIES:
         case FETCHCATEGORYCHILDREN:
         case FETCHCATEGORYSUBSET:
+        case FETCHCATEGORYLINKS:
         case FETCHCOF:
             if (result.has("category_id"))
             {
@@ -1002,6 +1037,7 @@ AISUpdate::AISUpdate(const LLSD& update, AISAPI::COMMAND_TYPE type, const LLSD&
         || (type == AISAPI::FETCHCATEGORYCATEGORIES)
         || (type == AISAPI::FETCHCATEGORYSUBSET)
         || (type == AISAPI::FETCHCOF)
+        || (type == AISAPI::FETCHCATEGORYLINKS)
         || (type == AISAPI::FETCHORPHANS);
     // parse update llsd into stuff to do or parse received items.
     mFetchDepth = MAX_FOLDER_DEPTH_REQUEST;
diff --git a/indra/newview/llaisapi.h b/indra/newview/llaisapi.h
index 973c82a847086f079f8009d81f3dc096efd7f9cd..53c74ae0780ea4326524c46bccdbc598311cf39b 100644
--- a/indra/newview/llaisapi.h
+++ b/indra/newview/llaisapi.h
@@ -62,6 +62,7 @@ class AISAPI
     static void FetchCategoryCategories(const LLUUID &catId, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
     static void FetchCategorySubset(const LLUUID& catId, const uuid_vec_t specificChildren, ITEM_TYPE type = AISAPI::ITEM_TYPE::INVENTORY, bool recursive = false, completion_t callback = completion_t(), S32 depth = 0);
     static void FetchCOF(completion_t callback = completion_t());
+    static void FetchCategoryLinks(const LLUUID &catId, completion_t callback = completion_t());
     static void FetchOrphans(completion_t callback = completion_t() );
     static void CopyLibraryCategory(const LLUUID& sourceId, const LLUUID& destId, bool copySubfolders, completion_t callback = completion_t());
 
@@ -81,6 +82,7 @@ class AISAPI
         FETCHCATEGORYSUBSET,
         FETCHCOF,
         FETCHORPHANS,
+        FETCHCATEGORYLINKS
     } COMMAND_TYPE;
 
 private:
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 454ac5d88c878c95b44608f3adf42b86f2f174b8..d4fc6a9f9de081c6f5bc560b3ead4bdc46b48c27 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -4612,6 +4612,35 @@ void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb)
     }
 }
 
+void callAfterCategoryLinksFetch(const LLUUID &cat_id, nullary_func_t cb)
+{
+    LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
+    if (AISAPI::isAvailable())
+    {
+        // Mark folder (update timer) so that background fetch won't request it
+        cat->setFetching(LLViewerInventoryCategory::FETCH_RECURSIVE);
+        // Assume that we have no relevant cache. Fetch folder, and items folder's links point to.
+        AISAPI::FetchCategoryLinks(cat_id,
+            [cb, cat_id](const LLUUID &id)
+            {
+                cb();
+                LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
+                if (cat)
+                {
+                    cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
+                }
+            });
+        }
+        else
+        {
+            LL_WARNS() << "AIS API v3 not available, can't use AISAPI::FetchCOF" << LL_ENDL;
+            // startup should have marked folder as fetching, remove that
+            cat->setFetching(LLViewerInventoryCategory::FETCH_NONE);
+            callAfterCategoryFetch(cat_id, cb);
+        }
+    
+}
+
 void add_wearable_type_counts(const uuid_vec_t& ids,
                               S32& clothing_count,
                               S32& bodypart_count,
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index f6aa30d8651eac6947b0558445ec67f5a8ecba83..43839e47a647ebd00cb1f1029362cd17d164b817 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -340,6 +340,7 @@ LLUUID findDescendentCategoryIDByName(const LLUUID& parent_id,const std::string&
 // Invoke a given callable after category contents are fully fetched.
 void callAfterCOFFetch(nullary_func_t cb);
 void callAfterCategoryFetch(const LLUUID& cat_id, nullary_func_t cb);
+void callAfterCategoryLinksFetch(const LLUUID &cat_id, nullary_func_t cb);
 
 // Wear all items in a uuid vector.
 void wear_multiple(const uuid_vec_t& ids, bool replace);
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index ed375661b896205042abc7ab838e3d4db140e024..586f1388ff9bdb787583559e26def4235e1fd79f 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -79,6 +79,8 @@
 const S32 LLInventoryModel::sCurrentInvCacheVersion = 3;
 BOOL LLInventoryModel::sFirstTimeInViewer2 = TRUE;
 
+S32 LLInventoryModel::sPendingSystemFolders = 0;
+
 ///----------------------------------------------------------------------------
 /// Local function declarations, constants, enums, and typedefs
 ///----------------------------------------------------------------------------
@@ -861,8 +863,9 @@ void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred
                     }
                     else
                     {
-                        LL_DEBUGS("Inventory") << "Created category: " << new_cat_id
+                        LL_WARNS("Inventory") << "Created category: " << new_cat_id
                             << " for type: " << preferred_type << LL_ENDL;
+                        sPendingSystemFolders--;
                     }
             }
             );
@@ -873,6 +876,10 @@ void LLInventoryModel::ensureCategoryForTypeExists(LLFolderType::EType preferred
                 << " because inventory is not usable" << LL_ENDL;
         }
     }
+    else
+    {
+        sPendingSystemFolders--;
+    }
 }
 
 const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
@@ -3253,6 +3260,9 @@ LLCore::HttpHandle LLInventoryModel::requestPost(bool foreground,
 
 void LLInventoryModel::createCommonSystemCategories()
 {
+    //amount of System Folder we should wait for
+    sPendingSystemFolders = 8;
+
 	gInventory.ensureCategoryForTypeExists(LLFolderType::FT_TRASH);
 	gInventory.ensureCategoryForTypeExists(LLFolderType::FT_FAVORITE);
 	gInventory.ensureCategoryForTypeExists(LLFolderType::FT_CALLINGCARD);
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index db159d480a0fb60e2092e436e6828a3400726676..a90ed2bf424fdc7d852e980b3c0f4710db53cb89 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -227,10 +227,14 @@ class LLInventoryModel
 	//--------------------------------------------------------------------
 public:
 	static BOOL getIsFirstTimeInViewer2();
+    static bool  isSysFoldersReady() { return (sPendingSystemFolders == 0); }
+
 private:
 	static BOOL sFirstTimeInViewer2;
 	const static S32 sCurrentInvCacheVersion; // expected inventory cache version
 
+    static S32 sPendingSystemFolders;
+
 /**                    Initialization/Setup
  **                                                                            **
  *******************************************************************************/
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 9f9e11776055f770cefc06cc4900af07e5789647..c925563919dc5114f8b33b40ca2b1b985855e5c8 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -1912,7 +1912,22 @@ bool idle_startup()
 		
         LLInventoryModelBackgroundFetch::instance().start();
 		gInventory.createCommonSystemCategories();
+        LLStartUp::setStartupState(STATE_INVENTORY_CALLBACKS );
+        display_startup();
+
+        return FALSE;
+    }
 
+    //---------------------------------------------------------------------
+    // STATE_INVENTORY_CALLBACKS 
+    //---------------------------------------------------------------------
+    if (STATE_INVENTORY_CALLBACKS  == LLStartUp::getStartupState())
+    {
+        if (!LLInventoryModel::isSysFoldersReady())
+        {
+            display_startup();
+            return FALSE;
+        }
         LLInventoryModelBackgroundFetch::instance().start();
         LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
         LLViewerInventoryCategory* cof = gInventory.getCategory(cof_id);
@@ -2850,8 +2865,15 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
 		bool do_append = false;
 		LLViewerInventoryCategory *cat = gInventory.getCategory(cat_id);
 		// Need to fetch cof contents before we can wear.
-		callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(),
+        if (do_copy)
+        {
+            callAfterCategoryFetch(LLAppearanceMgr::instance().getCOF(),
 							   boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append));
+        }
+        else
+        {
+            callAfterCategoryLinksFetch(cat_id, boost::bind(&LLAppearanceMgr::wearInventoryCategory, LLAppearanceMgr::getInstance(), cat, do_copy, do_append));
+        }
 		LL_DEBUGS() << "initial outfit category id: " << cat_id << LL_ENDL;
 	}
 
@@ -2904,6 +2926,7 @@ std::string LLStartUp::startupStateToString(EStartupState state)
 		RTNENUM( STATE_AGENT_SEND );
 		RTNENUM( STATE_AGENT_WAIT );
 		RTNENUM( STATE_INVENTORY_SEND );
+        RTNENUM(STATE_INVENTORY_CALLBACKS );
 		RTNENUM( STATE_MISC );
 		RTNENUM( STATE_PRECACHE );
 		RTNENUM( STATE_WEARABLES_WAIT );
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index fe8e215f76a1677dba7e09148eff65ab72f89efd..921f088423a5b5ba131a5fbef27eee53f918720d 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -71,6 +71,7 @@ typedef enum {
 	STATE_AGENT_SEND,				// Connect to a region
 	STATE_AGENT_WAIT,				// Wait for region
 	STATE_INVENTORY_SEND,			// Do inventory transfer
+	STATE_INVENTORY_CALLBACKS,		// Wait for missing system folders and register callbacks
 	STATE_MISC,						// Do more things (set bandwidth, start audio, save location, etc)
 	STATE_PRECACHE,					// Wait a bit for textures to download
 	STATE_WEARABLES_WAIT,			// Wait for clothing to download