Connected Connectors Crashing Revit

Hi all, I have a model health script that I have been running for a while. I am pulling over 100 metrics from Revit and everything has been relatively working fine except for one section (MEP connectors).

The goal of this section is to identify open-ended MEP elements that will mess with flow calculation and other things. My solution, I think is relatively simple. Grab specified elements, get all connectors on said element, and check to see if the connector is connected or not (I do understand links play a part here).

The problem is that it crashes Revit. In my testing on my personal computer, I have found that implementing a time.sleep of 0.1 seconds for every 25 elements processed prevents the crash. My best guess is that I am processing elements quicker than Revit can handle but I am not sure. My company recently got an impressive cloud computer and some files are crashing on it. I reduced the pause from 25 elements down to 20 so it will trigger the pause more frequently and this solves the problem for the cloud computer but increases the time to completion.

I have tested and noted this behavior in Revit Vessions from 2018 through 2023.

Do any of you have an idea what the problem could be or a better solution than implementing a pause?

categorieFilter = ['OST_CableTray','OST_CableTrayFitting','OST_Conduit','OST_ConduitFitting','OST_DuctCurves',
				'OST_FlexDuctCurves', 'OST_DuctFitting','OST_DuctTerminal','OST_ElectricalEquipment','OST_ElectricalFixtures',
				'OST_LightingDevices','OST_LightingFixtures','OST_MechanicalEquipment','OST_PipeCurves','OST_FlexPipeCurves',
				'OST_PipeFitting','OST_PlumbingFixtures','OST_SpecialityEquipment','OST_Sprinklers']
		
categorieFilter = rvt.getBuiltInCategory(categorieFilter)
categorieFilter = List[BuiltInCategory](categorieFilter) # sets the list up for the .net framwork
categorieFilter = ElementMulticategoryFilter(categorieFilter,False) # creates the filter (True value will remove Items from the selction)
#try:
allElements = FilteredElementCollector(doc).WhereElementIsNotElementType().WherePasses(categorieFilter).ToElements()
connectorsCount, unconnectedCount = 0, 0
notConnected = []
for count, element in enumerate(allElements):
	if count % 25 == 0:
		time.sleep(0.1)
	try:
		connectors = element.MEPModel.ConnectorManager.Connectors
	except:
		try:
			connectors = element.ConnectorManager.Connectors
		except:	
			continue
	added, typeAdded= True, []
	for connector in connectors:	
		connectorsCount += 1
		try:
			if not connector.IsConnected:
				conType = connector.Domain
				unconnectedCount += 1
				if added or conType not in typeAdded:
					notConnected.append(element.Name)
					added = False
					typeAdded.append(conType)
					conType = str(conType).replace('Domain','')
					csvRow(elementsCSV,("connectedConnector", element.Id, element.Name, conType, '', fileName))
		except:
			pass

Thank you,
Steven

Certainly not the case on the Revit side - it likely shouldn’t be an issue unless your data extraction runs faster than your memory/scratch disc can record (which shouldn’t be doable unless your system was configured by someone who really was not thinking ahead).

More likely you should be accessing this data in a more efficient way. That said if your tool is doing as much as it sounds you may want to move to a zero touch node for efficient processing, and there is a good example of how this works here: https://jeremytammik.github.io/tbc/a/1008_loose_connector.htm

Staying in the Python realm, the issue may be with the multiple try/except statements - these aren’t intended for flow control, and can lead to some performance issues, the likes of which can be similar to what you are seeing here. You also may want to try disposing elements when no longer needed in memory to ensure the code is memory efficient.

1 Like

The ConnectorManager class has the UnusedConnectors Property which may be the more efficient way to check

Adjust this line order
allElements = FilteredElementCollector(doc).WherePasses(categorieFilter).WhereElementIsNotElementType().ToElements()

Here is your code (sort of) refactored based on this Building Coder post Retrieve MEP Elements and Connectors

import clr

from System.Collections.Generic import List

clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager

clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import (
    BuiltInCategory,
    ElementMulticategoryFilter,
    FilteredElementCollector,
    FamilyInstance,
    MEPCurve,
)


def get_connectors(element):
    if isinstance(element, FamilyInstance):
        return element.MEPModel.ConnectorManager.Connectors
    if isinstance(element, MEPCurve):
        return element.ConnectorManager.Connectors


def get_unusedconnectors(element):
    if isinstance(element, FamilyInstance):
        return element.MEPModel.ConnectorManager.UnusedConnectors
    if isinstance(element, MEPCurve):
        return element.ConnectorManager.UnusedConnectors


doc = DocumentManager.Instance.CurrentDBDocument

bics = [
    BuiltInCategory.OST_CableTray,
    BuiltInCategory.OST_CableTrayFitting,
    BuiltInCategory.OST_Conduit,
    BuiltInCategory.OST_ConduitFitting,
    BuiltInCategory.OST_DuctCurves,
    BuiltInCategory.OST_DuctFitting,
    BuiltInCategory.OST_DuctTerminal,
    BuiltInCategory.OST_ElectricalEquipment,
    BuiltInCategory.OST_ElectricalFixtures,
    BuiltInCategory.OST_LightingDevices,
    BuiltInCategory.OST_LightingFixtures,
    BuiltInCategory.OST_MechanicalEquipment,
    # BuiltInCategory.OST_PipeCurves,
    BuiltInCategory.OST_PipeFitting,
    BuiltInCategory.OST_PlumbingFixtures,
    BuiltInCategory.OST_SpecialityEquipment,
    BuiltInCategory.OST_Sprinklers,
    # BuiltInCategory.OST_Wire,
]

cats = List[BuiltInCategory](bics)

emcf = ElementMulticategoryFilter(cats)

elements = (
    FilteredElementCollector(doc)
    .WherePasses(emcf)
    .WhereElementIsNotElementType()
    .ToElements()
)

OUT = filter(list, [get_unusedconnectors(element) for element in elements])
2 Likes

Thanks @Mike.Buttery, that does solve the crashing and is 20% faster (rough testing).

I cannot believe I missed the UnusedConnectors property. So much cleaner.

3 Likes