The referenced object is not valid, possibly because it has been deleted from the database, or its creation was undone

python
#1

I keep receiving the subject error message, also indicating a failure. Honestly I’ve been chasing this a bit and I’m at a loss, though it’s likely something very simple. It’s worth noting all the tasks successfully complete but there is no output due to this error. The second time the script runs on the same project, there is no error (probably because the tasks do not need to execute).

My solution is basically: 1) checking/creating a shared parameter in a project’s families, 2) checking/applying the same shared parameter to the project, 3) validating other properties in the applied families and inserting a value into the parameter inserted in stage 1.

Here are the parts of python that are tripping on the error:
this function:

def _CheckIN0(families):
	for f1 in families:
		famdoc = doc.EditFamily(f1)
		load1 = False
		load2 = False
		
		#get category for later
		cats.append(f1.FamilyCategory)
		
		try:
			param = famdoc.FamilyManager.get_Parameter(sParam)
			load1 = _AddParameter(famdoc, f1)
			_FilterNonBlankIN0(famdoc, f1)
			#results.append(sParam)
		except Exception, e:
			errors.append("112: "%e)

		#if load1 == True:
		if famdoc.FamilyManager.get_Parameter(sParam):
			results.append(famdoc.FamilyManager.get_Parameter(sParam))
			trans = Transaction(famdoc, "LoadFamily")
			trans.Start()
			try:
				famdoc.LoadFamily(doc, FamilyOption())
			except Exception,e:
				famdoc.LoadFamily(doc, True)
				errors.append("124: "%e)
			trans.Commit()
		famdoc.Close(False)

which calls this class:

class FamilyOption(IFamilyLoadOptions):
    def __init__(self): pass
    def OnFamilyFound(self, familyInUse, overwriteParameterValues):
    	overwriteParameterValues = True
    	return True
    def OnSharedFamilyFound(self,familyInUse, source, overwriteParameterValues): return True

Thank you!!

#2

I think this should be doc, not famdoc…

trans = Transaction(famdoc, "LoadFamily")

#3

Hey @SeanP thank you for responding! Unfortunately, that resulted in:

TypeError: expected str, got Document

#4

So from the snip you have given us I think this:

  1. In Project Environment (doc)
  2. Edit Family (famdoc)
  3. Add Parameter
  4. Check Parameter Exists
  5. Load back into Project.(famdoc INTO doc)

If this is true, I think you need to use famdoc.Close(true).

See here for reference:

#5

Thank you again for the tip! The effect of that would be an instruction for Revit to save the family files upon reloading into the project. If you think about the process of opening a project, choosing Edit Family, editing the family and then reloading the family into the project, that Family.Close(bool) step would indicate to Revit if the user would like to save the family file, which in this case, I do not. The second class in my OP automates the dialog upon family reentry into the project (no change, overwrite (including bool parameter values), and overwrite a nested (“Shared”) family that is hosted into another family.

I have been able to eliminate the following possibilities:
• Nested issues
• Category-based reload limits
• Transactions

It may be a flaw in the IFamilyLoadOptions method that could generate a fail no matter the outcome.

#6

So here is code that I use to do some cleaning of families. I think something to note here is that I don’t believe you have to be IN a transaction to load families into the model.

import System
import clr
clr.AddReference("RevitNodes")
import Revit
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
clr.AddReference("RevitAPI")
clr.AddReference('DSCoreNodes')
from DSCore import *
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import sys
pyt_path = r'C:\Program Files (x86)\IronPython 2.7\Lib'
sys.path.append(pyt_path)

ProjectDoc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

families = IN[0]
if not isinstance(paths, list): paths = [paths]
cats = List.Flatten([IN[1]],1)

save = IN[2]
load = IN[3]

class FamilyOption(IFamilyLoadOptions):
    def OnFamilyFound(self, familyInUse, overwriteParameterValues):
        overwriteParameterValues = True
        return True

    def OnSharedFamilyFound(
            self, sharedFamily, familyInUse, source, overwriteParameterValues):
        source = FamilySource.Family
        overwriteParameterValues = True
        return True

delIds = []
errorReport = None
try:
	for fam in families:
		trans = Transaction(doc,'del')
		trans.Start()

                famDoc = ProjectDoc.EditFamily(fam)
		#Do your work here for your parameters
			
		trans.Commit()
		trans.Dispose()
			
		if load:
			famDoc.LoadFamily(ProjectDoc,FamilyOption())
		
		if save:
			opt = SaveAsOptions()
			opt.OverwriteExistingFile = True
			opt.Compact = True
			opt.MaximumBackups = 1
			doc.SaveAs(path,opt)	
			doc.Close(False)
		else:
			doc.Close(False)
			
except:
	import traceback
	errorReport = traceback.format_exc()

if errorReport is None:
    OUT = delIds
else:
    OUT = errorReport
#7

You’re brilliant and a saint! Thank you!

It took some time comparing the two and considering/applying the differences. At the end of it, I removed 2 of the functions the original called, and restructured when the transaction and load family should be called. The other 2 functions didn’t end up as robust as originally intended. So you’ll see fragments of them in the final result that I will be cleaning out. Also, you’re absolutely right in that the load family does not need to be in a transaction.

Here’s what I ended up with:

def _CheckIN0(families):
	trans1 = TransactionManager.Instance
	trans1.ForceCloseTransaction() #just to make sure everything is closed down
	for f1 in families:
		_paramType = ParameterType.Text
		_paramGroup = BuiltInParameterGroup.PG_IDENTITY_DATA
		_paramName = cParam
		_groupName = "Assets"
		cc = ""
		value = ""
		
		famdoc = doc.EditFamily(f1)
		famMan = famdoc.FamilyManager
		trans1.EnsureInTransaction(famdoc)
		
		#get category for later
		cats.append(f1.FamilyCategory)
		
		#add shared parameter to families
		try:
			file = app.OpenSharedParameterFile()
		except Exception,e:
			errors.append("83: "%e)
			pass
			
		try:
			param = famMan.get_Parameter(sParam)
			params = famMan.Parameters

			eDef = DefFile(file, _groupName, cParam)
			famdoc.FamilyManager.AddParameter(eDef,_paramGroup, False)
		    
			for p1 in params:
				if p1.Definition.Name == sParam:
					ac = p1
			for p2 in params:
				if p2.Definition.Name == cParam:
					cc = p2
			familyTypesItor = famMan.Types.ForwardIterator()
			familyTypesItor.Reset()
			while (familyTypesItor.MoveNext()):
				ft = familyTypesItor.Current
				value = ft.AsString(ac)
				custom = ft.AsString(cc)
				
			if value > "":
				typeinfo = []
				typeinfo.append(f)
				typeinfo.append(ft.Name)
				typeinfo.append(custom)
				typeinfo.append(value)
				listings.Add(typeinfo)
				
			trans1.ForceCloseTransaction()
			
		except Exception, e:
			errors.append(e)
			trans1.ForceCloseTransaction()
			
		famdoc.LoadFamily(doc, FamilyOption())
		famdoc.Close(False)