# ReferenceError: BMesh data of type BMesh has been removed cause and fix

I've made a lot of scripts that had this error: ReferenceError: BMesh data of type BMesh has been removed. While I've usually found workarounds I would like to know what causes this error and how to fix it for future scripts.

Edit: This is my fence.

import bpy
import bmesh

class Create():
mesh = bpy.context.active_object
bm = bmesh.from_edit_mesh(mesh.data)

def Verts(self,pose):
self.bm.verts.ensure_lookup_table()
self.bm.verts.new((1,1,1))
bmesh.update_edit_mesh(self.mesh.data

class Modal(bpy.types.Operator):
bl_idname = "object.modal"
bl_label = "Modal Op"
bl_description = "Other thingy"
bl_options = {"REGISTER"}
@classmethod
def poll(cls, context):
return True

def invoke(self, context, event):
bpy.ops.object.mode_set(mode='EDIT')
return {"RUNNING_MODAL"}

def modal(self, context, event):
c = Create()
if event.type == "LEFTMOUSE" and event.value == "PRESS":
c.Verts((0,0,1))
print("Test")

if event.type in {"RIGHTMOUSE", "ESC"}:

return {"CANCELLED"}
keys = ["WHEELUPMOUSE","WHEELDOWNMOUSE","MIDDLEMOUSE","LEFTMOUSE"]

for i in keys:
if event.type == i:
return{"PASS_THROUGH"}

return {"RUNNING_MODAL"}
def register():
bpy.utils.register_class(Modal)

def unregister():
bpy.utils.unregister_class(Modal)

if __name__ == "__main__":
register()

• Most commonly this is caused by making an edit mode bmesh.from_edit_mesh(me), and then toggling object mode. – batFINGER May 1 '18 at 5:58
• How can I avoid it? – sajdnv May 1 '18 at 11:19
• Don't toggle object / edit mode with an active live edit bmesh. Suggest posting some samples from your scripts demonstrating how you invoke the error. Otherwise it becomes a guessing game. Basic rule of thumb I use is if's not needed as a UI tool, use object mode bmesh. – batFINGER May 1 '18 at 11:30
• How and when do you want the operator active? If it's an edit mode tool suggest making switch to object mode cancel the operator. If context.mode != 'EDIT_MESH'. – batFINGER May 1 '18 at 12:16
• I would do that but I want to stay in edit mode when it’s cancelled. – sajdnv May 1 '18 at 12:23

Assigning class properties

The error you were seeing was in the way you were setting the bmesh in your Create class. The property bm will be the bmesh for the context edit mesh when the sctipt was run, rather than, what you want, when the operator is invoked.

Suggest rather than instancing the class in modal loop, make one instance in invoke and use that. Add a constructor to your Create class with an argument context to ensure it is for the context mesh.

Example where the bm is set as a class property of the operator.

import bpy
import bmesh

bmeshes = {}

class Modal(bpy.types.Operator):
bl_idname = "object.modal"
bl_label = "Modal Op"
bl_description = "Other thingy"
bl_options = {"REGISTER"}

bm = None

@classmethod
def poll(cls, context):
return True

@classmethod
def bmesh(cls, context):
me = context.edit_object.data
cls.bm = bmesh.from_edit_mesh(me)

def invoke(self, context, event):
bpy.ops.object.mode_set(mode='EDIT')
self.bmesh(context)
return {"RUNNING_MODAL"}

return self.bm.verts.new(loc)

def modal(self, context, event):
# no longer in edit mode
if context.mode != 'EDIT_MESH':
self.bm.free()
self.bm = None
return {'CANCELLED'}

me = context.edit_object.data
if self.bm is None or not self.bm.is_valid:
# in edit mode so try make a new bmesh
self.bmesh(context)
if event.type == "LEFTMOUSE" and event.value == "PRESS":
# update after all operations
self.bm.verts.index_update()
bmesh.update_edit_mesh(me)

if event.type in {"RIGHTMOUSE", "ESC"}:
return {"CANCELLED"}

if event.type in ["WHEELUPMOUSE","WHEELDOWNMOUSE","MIDDLEMOUSE","LEFTMOUSE"]:
return{"PASS_THROUGH"}

return {"RUNNING_MODAL"}

def register():
bpy.utils.register_class(Modal)

def unregister():
bpy.utils.unregister_class(Modal)

if __name__ == "__main__":
register()


For panel code to have an edit mode bmesh I often use a global dictionary

bm = bmeshes.setdefault(me.name, bmesh.from_edit_mesh(me))


which can be set / cleared using the panels' poll method.