#1060·BlenderGIS

Dropdown labels show garbled text: EnumProperty items callbacks don't keep a reference to the returned strings

Author: cvonkCreated Aug 19, 2026Updated Aug 19, 2026

Dropdown labels show garbled text: EnumProperty items callbacks don't keep a reference to the returned strings

To be honest Claude Code found this for me, after I discovered the issue.

BlenderGIS 2.2.14 · Blender 5.2 · Windows 11

Summary

Every dynamic EnumProperty items callback in the addon builds its item list in a local variable and returns it. Blender's Python API requires the caller to keep a reference to those strings; otherwise they are garbage-collected while Blender is still using them, and the UI draws freed memory.

The visible result is mojibake in dropdowns. It is most obvious on entries whose label contains non-ASCII characters, which are heap-allocated rather than interned and so are reused sooner.

From the bpy.props.EnumProperty docs:

There is a known bug with using a callback, Python must keep a reference to the strings returned by the callback or Blender will misbehave or even crash.

Steps to reproduce

  1. Create a mesh object with a non-ASCII name, e.g. Mühlbacher Höhenweg - DEM.
  2. Georeference the scene (GIS ▸ Geoscene) so the "on mesh" mode is offered.
  3. GIS ▸ Import ▸ Georeferenced raster, pick any GeoTIFF.
  4. Set Mode = "Basemap on mesh" and open the Objects dropdown.

Expected: the object's name. Actual: garbled characters. The entry for the ASCII-named objects in the same scene usually renders correctly, which is what makes it look data-dependent.

Cause

operators/io_import_georaster.py:62

python
def listObjects(self, context):
    objs = []                                   # local - freed on return
    for index, object in enumerate(bpy.context.scene.objects):
        if object.type == 'MESH':
            objs.append((str(index), object.name, "Object named " + object.name))
    return objs

objs and the tuples inside it are dropped as soon as the function returns, but Blender keeps pointing at the strings until the next redraw.

Scope

This is not isolated to one dropdown. Grepping 2.2.14 for def list*(self, context) finds 19 callbacks and none of them retains a reference:

file line callback
operators/io_import_georaster.py 62 listObjects
operators/io_import_georaster.py 104 listSubdivisionModes
operators/io_import_osm.py 137 listObjects
operators/io_import_shp.py 107 listFields
operators/io_import_shp.py 124 listObjects
operators/io_export_shp.py 56 listCollections
operators/add_camera_exif.py 226 listGeoCam
operators/view3d_mapviewer.py 363 / 370 / 382 listSources / listGrids / listLayers
prefs.py 95 / 161 / 233 / 246 listPredefCRS / listOsmTags / listOverpassServer / listDemServer
operators/nodes_terrain_analysis_reclassify.py 776 listSVG

The ones building labels from user-supplied names are the ones that show it in practice: object names, collection names, shapefile field names, layer names.

Suggested fix

Hold the list at module level so the strings outlive the call:

python
_objects_enum = []          # module level - keeps the strings alive

def listObjects(self, context):
    global _objects_enum
    _objects_enum = [
        (str(i), o.name, "Object named " + o.name)
        for i, o in enumerate(bpy.context.scene.objects) if o.type == 'MESH'
    ]
    return _objects_enum

A shared helper would avoid repeating the idiom 19 times, e.g. a small cached_enum(key, builder) in utils/ that stores each result in a module-level dict keyed by callback name.

Notes

  • The selection still works: the enum's identifier is the index string and scn.objects[int(self.objectsLst)] resolves correctly. Only the drawn label is corrupt — so the bug is cosmetic, but it makes the dropdown unusable when you cannot read which object you are choosing.
  • Workaround for users: temporarily rename the object to ASCII before importing.
  • Reproduced on Blender 5.2; the caveat is long-standing in the Blender API and is not specific to a Blender version.