diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 172cdbf08a6ccdc2d8969ada8f03054d57621830..877c50896baeeb7bc40b8786b2b1465fb211d4c3 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -1736,7 +1736,6 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) {
         pCB->drawData.clear();
         pCB->currentDrawData.buffers.clear();
         pCB->vertex_buffer_used = false;
-        pCB->primaryCommandBuffer = VK_NULL_HANDLE;
         // If secondary, invalidate any primary command buffer that may call us.
         if (pCB->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) {
             invalidateCommandBuffers(dev_data,
@@ -2509,6 +2508,8 @@ static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NO
     // Track in-use for resources off of primary and any secondary CBs
     bool skip = false;
 
+    // TODO: inline this function into sole caller
+
     // If USAGE_SIMULTANEOUS_USE_BIT not set then CB cannot already be executing
     // on device
     skip |= validateCommandBufferSimultaneousUse(dev_data, pCB, current_submit_count);
@@ -2517,16 +2518,6 @@ static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NO
 
     for (auto pSubCB : pCB->linkedCommandBuffers) {
         skip |= validateResources(dev_data, pSubCB);
-        // TODO: replace with invalidateCommandBuffers() at recording.
-        if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) &&
-            !(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
-            log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, 0,
-                    __LINE__, VALIDATION_ERROR_31a00092, "DS",
-                    "Commandbuffer 0x%p was submitted with secondary buffer 0x%p but that buffer has subsequently been bound to "
-                    "primary cmd buffer 0x%p and it does not have VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT set. %s",
-                    pCB->commandBuffer, pSubCB->commandBuffer, pSubCB->primaryCommandBuffer,
-                    validation_error_map[VALIDATION_ERROR_31a00092]);
-        }
     }
 
     skip |= validateCommandBufferState(dev_data, pCB, "vkQueueSubmit()", current_submit_count, VALIDATION_ERROR_31a00090);
@@ -4109,7 +4100,7 @@ VKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount,
 }
 
 // For given cb_nodes, invalidate them and track object causing invalidation
-void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj) {
+void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj, bool track_invalidator) {
     for (auto cb_node : cb_nodes) {
         if (cb_node->state == CB_RECORDING) {
             log_msg(dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
@@ -4120,11 +4111,13 @@ void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLO
         else {
             cb_node->state = CB_INVALID_COMPLETE;
         }
-        cb_node->broken_bindings.push_back(obj);
+        if (track_invalidator) {
+            cb_node->broken_bindings.push_back(obj);
+        }
 
         // if secondary, then propagate the invalidation to the primaries that will call us.
         if (cb_node->createInfo.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY) {
-            invalidateCommandBuffers(dev_data, cb_node->linkedCommandBuffers, obj);
+            invalidateCommandBuffers(dev_data, cb_node->linkedCommandBuffers, obj, track_invalidator);
         }
     }
 }
@@ -8320,6 +8313,13 @@ VKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uin
                         pCommandBuffers[i], pCB->commandBuffer);
                     pCB->beginInfo.flags &= ~VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
                 }
+                if (pSubCB->linkedCommandBuffers.size()) {
+                    // TODO: adjust message support so we can report an accurate error message for this.
+                    invalidateCommandBuffers(dev_data, pSubCB->linkedCommandBuffers,
+                                             {HandleToUint64(pCommandBuffers[i]), kVulkanObjectTypeCommandBuffer},
+                                             false /* don't track invalidator. we've already complained. */);
+                    // TODO: consistent strategy for removing links.
+                }
             }
             if (!pCB->activeQueries.empty() && !dev_data->enabled_features.inheritedQueries) {
                 skip |=
@@ -8336,7 +8336,6 @@ VKAPI_ATTR void VKAPI_CALL CmdExecuteCommands(VkCommandBuffer commandBuffer, uin
             for (auto ilm_entry : pSubCB->imageLayoutMap) {
                 SetLayout(dev_data, pCB, ilm_entry.first, ilm_entry.second);
             }
-            pSubCB->primaryCommandBuffer = pCB->commandBuffer;
             pCB->linkedCommandBuffers.insert(pSubCB);
             pSubCB->linkedCommandBuffers.insert(pCB);
             for (auto &function : pSubCB->queryUpdates) {
diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h
index 16548682b0f0dc786c994b4444a111abdbf61089..0cb6ecee4bbfd96917480721049564aebfe39be1 100644
--- a/layers/core_validation_types.h
+++ b/layers/core_validation_types.h
@@ -671,7 +671,6 @@ struct GLOBAL_CB_NODE : public BASE_NODE {
     std::vector<DRAW_DATA> drawData;
     DRAW_DATA currentDrawData;
     bool vertex_buffer_used;  // Track for perf warning to make sure any bound vtx buffer used
-    VkCommandBuffer primaryCommandBuffer;
     // Track images and buffers that are updated by this CB at the point of a draw
     std::unordered_set<VkImageView> updateImages;
     std::unordered_set<VkBuffer> updateBuffers;
@@ -787,7 +786,6 @@ const PHYS_DEV_PROPERTIES_NODE *GetPhysDevProperties(const layer_data *device_da
 const VkPhysicalDeviceFeatures *GetEnabledFeatures(const layer_data *device_data);
 const DeviceExtensions *GetEnabledExtensions(const layer_data *device_data);
 
-void invalidateCommandBuffers(const layer_data *, std::unordered_set<GLOBAL_CB_NODE *> const &, VK_OBJECT);
 bool ValidateMemoryIsBoundToBuffer(const layer_data *, const BUFFER_STATE *, const char *, UNIQUE_VALIDATION_ERROR_CODE);
 bool ValidateMemoryIsBoundToImage(const layer_data *, const IMAGE_STATE *, const char *, UNIQUE_VALIDATION_ERROR_CODE);
 void AddCommandBufferBindingSampler(GLOBAL_CB_NODE *, SAMPLER_STATE *);
@@ -796,7 +794,7 @@ void AddCommandBufferBindingImageView(const layer_data *, GLOBAL_CB_NODE *, IMAG
 void AddCommandBufferBindingBuffer(const layer_data *, GLOBAL_CB_NODE *, BUFFER_STATE *);
 void AddCommandBufferBindingBufferView(const layer_data *, GLOBAL_CB_NODE *, BUFFER_VIEW_STATE *);
 bool ValidateObjectNotInUse(const layer_data *dev_data, BASE_NODE *obj_node, VK_OBJECT obj_struct, UNIQUE_VALIDATION_ERROR_CODE error_code);
-void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj);
+void invalidateCommandBuffers(const layer_data *dev_data, std::unordered_set<GLOBAL_CB_NODE *> const &cb_nodes, VK_OBJECT obj, bool track_invalidator=true);
 void RemoveImageMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info);
 void RemoveBufferMemoryRange(uint64_t handle, DEVICE_MEM_INFO *mem_info);
 bool ClearMemoryObjectBindings(layer_data *dev_data, uint64_t handle, VulkanObjectType type);