BUG - Grasshopper Blocks - Cannot Delete - Trapped In Memory?


It appears that when I add a Model Block Instance to the Rhino Model via a Grasshopper Script even after disabling the Content Cache, deleting the block, and running the Purge Command, the InstanceObject is still trapped in “memory” and exists in the layer table despite it not existing in GH or the Block Manager.

Video Showcasing Issue:

I found this because I had a Python script that was querying InstanceDefinition UserText and it was crashing Rhino.

I traced the issue to Grasshopper keeping these “empty?” references in memory still.

Tested on 8.8 and 8.7 builds

Perhaps this is not a bug and just my limited understanding of how the InstanceDefinition Table works in scripting? Do I need to manually call a refresh or something?

My expectation would be that if Purge was ran on blocks and if all blocks have been deleted in the Rhino Model and GH model then I shouldn’t be able to “access” any of those blocks via scripting?

Example of a “lighter” error when listing blocks in the model if these undeleted “ghost blocks” are present, other errors involve User Text and Grasshopper Proxy Tables

[ERROR] FATAL UNHANDLED EXCEPTION: Python.Runtime.PythonException: 'NoneType'

Python Script For Testing:
20240609_Rhino_Grasshopper_Scripting_Conflict_01a.py (483 Bytes)

Sys Info

Rhino 8 SR8 2024-6-6 (Rhino 8, 8.8.24158.03001, Git hash:master @ c3cb4a9dc98ee25dc1f6e221e25c58a938d8d81a)
License type: Commercial, build 2024-06-06
License details: Cloud Zoo

Windows 11 (10.0.22631 SR0.0) or greater (Physical RAM: 64GB)
.NET 7.0.17

Computer platform: LAPTOP - Plugged in [99% battery remaining]

Standard graphics configuration.
Primary display: DisplayLink USB Device (DisplayLink) Memory: 0MB, Driver date: 2-9-2024 (M-D-Y).
> External USB display device with 4 adapter port(s)
- Windows Main Display attached to adapter port 0
- Secondary monitor attached to adapter port 1
Primary OpenGL: NVIDIA GeForce RTX 3080 Ti Laptop GPU (NVidia) Memory: 16GB, Driver date: 1-15-2023 (M-D-Y). OpenGL Ver: 4.6.0 NVIDIA 528.24
> Integrated accelerated graphics device with 4 adapter port(s)
- Video pass-through to primary display device

Secondary graphics devices.
Intel(R) Iris(R) Xe Graphics (Intel) Memory: 1GB, Driver date: 10-26-2022 (M-D-Y).
> Integrated graphics device with 4 adapter port(s)
- There are no monitors attached to this device. Laptop lid is probably closed
DisplayLink USB Device (DisplayLink) Memory: 0MB, Driver date: 2-9-2024 (M-D-Y).
> External USB display device with 0 adapter port(s)
- There are no monitors attached to this device. Laptop lid is probably closed

OpenGL Settings
Safe mode: Off
Use accelerated hardware modes: On
Redraw scene when viewports are exposed: On
Graphics level being used: OpenGL 4.6 (primary GPU’s maximum)

Anti-alias mode: 4x
Mip Map Filtering: Linear
Anisotropic Filtering Mode: High

Vendor Name: NVIDIA Corporation
Render version: 4.6
Shading Language: 4.60 NVIDIA
Driver Date: 1-15-2023
Driver Version:
Maximum Texture size: 32768 x 32768
Z-Buffer depth: 24 bits
Maximum Viewport size: 32768 x 32768
Total Video Memory: 16 GB

Rhino plugins that do not ship with Rhino
C:\Users\micha\AppData\Roaming\McNeel\Rhinoceros\packages\8.0\Crash\1.4.2-beta\Crash.rhp “Crash”
C:\Program Files\Enscape\Enscape.Rhino.Plugin-net48\Enscape.Rhino8.Plugin.dll “Enscape.Rhino8.Plugin” 0.0.24138.1238
C:\ProgramData\McNeel\Rhinoceros\7.0\Plug-ins\Datasmith Rhino Exporter (d1fdc795-b334-4933-b680-088119cdc6bb)\DatasmithRhino7.rhp “Datasmith Exporter”

Rhino plugins that ship with Rhino
C:\Program Files\Rhino 8\Plug-ins\Commands.rhp “Commands” 8.8.24158.3001
C:\Program Files\Rhino 8\Plug-ins\rdk.rhp “Renderer Development Kit”
C:\Program Files\Rhino 8\Plug-ins\RhinoRenderCycles.rhp “Rhino Render” 8.8.24158.3001
C:\Program Files\Rhino 8\Plug-ins\rdk_etoui.rhp “RDK_EtoUI” 8.8.24158.3001
C:\Program Files\Rhino 8\Plug-ins\NamedSnapshots.rhp “Snapshots”
C:\Program Files\Rhino 8\Plug-ins\MeshCommands.rhp “MeshCommands” 8.8.24158.3001
C:\Program Files\Rhino 8\Plug-ins\IronPython\RhinoDLR_Python.rhp “IronPython” 8.8.24158.3001
C:\Program Files\Rhino 8\Plug-ins\RhinoCycles.rhp “RhinoCycles” 8.8.24158.3001
C:\Program Files\Rhino 8\Plug-ins\Grasshopper\GrasshopperPlugin.rhp “Grasshopper” 8.8.24158.3001
C:\Program Files\Rhino 8\Plug-ins\RhinoCode\RhinoCodePlugin.rhp “RhinoCodePlugin” 8.8.24158.3001
C:\Program Files\Rhino 8\Plug-ins\Toolbars\Toolbars.rhp “Toolbars” 8.8.24158.3001
C:\Program Files\Rhino 8\Plug-ins\3dxrhino.rhp “3Dconnexion 3D Mouse”
C:\Program Files\Rhino 8\Plug-ins\Displacement.rhp “Displacement”
C:\Program Files\Rhino 8\Plug-ins\SectionTools.rhp “SectionTools”

Thank you for your help!

Okay after much more digging I realized this is not a bug but the way the the InstanceDefinition Table works in Rhino apparently. Nothing gets “deleted” but rather tagged as it being deleted so a “version of itself” still exists in the table despite it having no Name or info once it is “deleted”.

This was very confusing to me but I think it’s all working now. Sharing here in case anyone stumbles across this in the future.

This post solved it for me:

Example Code That Doesn’t Crash (Check If The InstanceDefinition Is Not “Deleted” First):

import Rhino
import scriptcontext as sc

def search_and_clean_block_instances():
    block_instances = sc.doc.InstanceDefinitions if hasattr(sc.doc, 'InstanceDefinitions') else []

    if block_instances:
        for instance in block_instances:
            if not instance.IsDeleted:
                # Print instance definition
                Rhino.RhinoApp.WriteLine(f"InstanceDefinition: {instance.Name} ({instance.Index})")
                Rhino.RhinoApp.WriteLine("Instance Exists In Table")
        Rhino.RhinoApp.WriteLine("No Blocks Exist")

if __name__ == "__main__":