Instrucciones de origen · Vista previa de solo lectura
name
blender-errors-context
description
Use when debugging Blender RuntimeError from restricted context, operator poll() failures, or wrong context for bpy.ops calls. Prevents the #1 Blender Python error: calling operators or accessing context attributes from wrong areas (e.g., timer callbacks, draw handlers). Covers context override removal in 4.0+, temp_override migration, and context-dependent attribute access patterns. Keywords: RuntimeError, restricted context, poll failure, context override, temp_override, bpy.ops error, wrong context, modal context, Blender context error, operator not available, cannot call operator.
license
MIT
compatibility
Designed for Claude Code. Requires Python 3.x.
metadata
{"author":"OpenAEC-Foundation","version":"1.0"}
dependencies
["blender-syntax-operators","blender-core-api"]
Blender Context Errors: Diagnosis and Resolution
Purpose
This skill enables diagnosis and resolution of Blender Python context errors. Context errors are the most common category of Blender scripting failures. They occur when code accesses members or calls operators in situations where the required context is unavailable, restricted, or incorrectly configured.
bpy.context
bpy.ops
Scope
RuntimeError from restricted context access (handlers, timers, draw callbacks)
Operator poll() failures and incorrect context for bpy.ops calls
Context override removal in Blender 4.0+ and temp_override() migration
draw() methods of bpy.types.Panel, bpy.types.Header, bpy.types.Menu
bpy.app.timers callbacks
Background threads (NEVER access bpy.context from threads)
Error messages:
RuntimeError: restricted context element 'active_object'
RuntimeError: Calling operator "bpy.ops.object.select_all" error, can't modify blend data in this state
Rule: In restricted contexts, use bpy.data for read-only access. NEVER call bpy.ops or modify blend data. To defer work to a safe context, use bpy.app.timers.register().
# Blender 3.2+import bpy
defmy_handler(scene, depsgraph):
# WRONG: bpy.context.active_object raises RuntimeError# WRONG: bpy.ops.object.delete() raises RuntimeError# CORRECT: read-only access via bpy.data
obj = bpy.data.objects.get("Cube")
if obj isnotNone:
print(obj.location)
# CORRECT: defer modifications to a timerdefdeferred():
bpy.data.objects["Cube"].location.x += 1.0returnNone# do not repeat
bpy.app.timers.register(deferred)
bpy.app.handlers.depsgraph_update_post.append(my_handler)
1.2 Operator poll() Failures
When: An operator's poll() classmethod returns False because required context conditions are not met.
Error message:
RuntimeError: Operator bpy.ops.object.mode_set.poll() failed, context is incorrect
Common causes:
Operator
Required context
bpy.ops.object.mode_set()
Active object exists, is visible, is selectable
bpy.ops.mesh.subdivide()
Active object is mesh, in Edit Mode
bpy.ops.object.parent_set()
2+ objects selected, one active
bpy.ops.uv.unwrap()
Active mesh in Edit Mode, UV map exists
bpy.ops.object.convert()
Active object exists, correct type
Rule: ALWAYS check poll() before calling an operator, OR set up the required context explicitly.
# Blender 3.2+import bpy
obj = bpy.data.objects.get("Cube")
if obj isNone:
raise RuntimeError("Object 'Cube' not found")
# Ensure context: select and activate
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
# Check poll before callingif bpy.ops.object.mode_set.poll():
bpy.ops.object.mode_set(mode='EDIT')
1.3 Context Override Errors (Version-Critical)
BREAKING CHANGE in Blender 4.0: Dictionary-based context overrides are REMOVED.
# Blender 3.x ONLY: REMOVED in 4.0
override = bpy.context.copy()
override['area'] = area
override['region'] = region
bpy.ops.view3d.camera_to_view(override) # TypeError in 4.0+
Blender 3.2+ (REQUIRED in 4.0+): Use bpy.context.temp_override().
# Blender 3.2+ (works in 3.2, 3.3, ..., 4.0, 4.1, ..., 5.x)import bpy
area = next(a for a in bpy.context.screen.areas if a.type == 'VIEW_3D')
region = next(r for r in area.regions if r.type == 'WINDOW')
with bpy.context.temp_override(area=area, region=region):
bpy.ops.view3d.camera_to_view()
Rule: ALWAYS use bpy.context.temp_override() for context overrides. NEVER use dictionary-based overrides — they fail silently in 3.6 and raise TypeError in 4.0+.
1.4 Modal Operator Context
When: Modal operators lose context between invoke() and modal() calls, or access area/region data that changes between frames.
Rule: Store required context references during invoke(). Do NOT rely on bpy.context.area or bpy.context.region persisting in modal().
# Blender 3.2+import bpy
classEXAMPLE_OT_modal(bpy.types.Operator):
bl_idname = "example.modal_op"
bl_label = "Modal Example"definvoke(self, context, event):
# Store references during invokeself._area = context.area
self._region = context.region
context.window_manager.modal_handler_add(self)
return {'RUNNING_MODAL'}
defmodal(self, context, event):
if event.type == 'ESC':
return {'CANCELLED'}
# Use stored references, not context.areaifself._area.type != 'VIEW_3D':
return {'CANCELLED'}
return {'PASS_THROUGH'}
1.5 Context-Dependent Attribute Access
When: Code accesses bpy.context attributes that are only available in specific editor types or modes.
Attributes with context requirements:
Attribute
Requires
context.edit_object
Object in Edit Mode
context.active_bone
Armature in Edit Mode
context.active_pose_bone
Armature in Pose Mode
context.sculpt_object
Object in Sculpt Mode
context.image_paint_object
Object in Texture Paint Mode
context.selected_editable_bones
Armature in Edit Mode
context.visible_pose_bones
Armature in Pose Mode
Rule: ALWAYS check mode before accessing mode-specific context attributes. These attributes return None or raise AttributeError when the mode does not match.
# Blender 3.2+import bpy
# WRONG: may be None if not in Edit Mode# verts = bpy.context.edit_object.data.vertices# CORRECT: check mode first
obj = bpy.context.active_object
if obj isnotNoneand obj.mode == 'EDIT':
edit_obj = bpy.context.edit_object
# work with edit_obj
2. Stale Reference Errors
2.1 Undo Invalidates All References
When: After bpy.ops.ed.undo() or user Ctrl+Z, ALL previously stored references to Blender data become invalid.
Error message:
ReferenceError: StructRNA of type Object has been removed
Rule: NEVER store persistent references to bpy.types instances across operations that may trigger undo. Re-fetch by name after undo.
# Blender 3.2+import bpy
# WRONG: reference becomes stale after undo
obj = bpy.data.objects["Cube"]
bpy.ops.ed.undo()
print(obj.location) # ReferenceError# CORRECT: re-fetch after undo
obj_name = "Cube"
bpy.ops.ed.undo()
obj = bpy.data.objects.get(obj_name)
if obj isnotNone:
print(obj.location)
2.2 Data Modification Invalidates References
When: Operations that add or remove data blocks (objects, meshes, materials) may invalidate existing Python references to the same collection.
Rule: After any operation that modifies bpy.data collections, re-fetch references by name. NEVER iterate a collection while modifying it.
# Blender 3.2+import bpy
# WRONG: modifying collection during iterationfor obj in bpy.data.objects:
bpy.data.objects.remove(obj) # invalidates iterator# CORRECT: collect names first, then remove
names = [obj.name for obj in bpy.data.objects if obj.type == 'MESH']
for name in names:
obj = bpy.data.objects.get(name)
if obj isnotNone:
bpy.data.objects.remove(obj)
2.3 Mode Change Invalidates Mesh References
When: Switching between Object Mode and Edit Mode invalidates bmesh.from_edit_mesh() references and mesh data access patterns.
Rule: ALWAYS obtain fresh mesh/bmesh references after mode changes. Free BMesh instances when done.
# Blender 3.2+import bpy
import bmesh
obj = bpy.context.active_object
bpy.ops.object.mode_set(mode='EDIT')
bm = bmesh.from_edit_mesh(obj.data)
bm.verts.ensure_lookup_table()
# ... perform edits ...
bmesh.update_edit_mesh(obj.data)
# Do NOT call bm.free() for from_edit_mesh: Blender manages it
bpy.ops.object.mode_set(mode='OBJECT')
# bm is now INVALID: do not use
3. Resolution Decision Tree
When encountering a context error, follow this sequence:
1. Is the error "restricted context element"?
YES → Code runs in a handler, timer, or draw callback.
→ Use bpy.data for read-only access.
→ Defer modifications with bpy.app.timers.register().
2. Is the error "poll() failed"?
YES → Check operator requirements (mode, selection, active object).
→ Set up context: activate object, set mode, ensure selection.
→ Use temp_override() if area/region context is needed.
3. Is the error about context overrides (TypeError)?
YES → Blender 4.0+ removed dict-based overrides.
→ Migrate to bpy.context.temp_override().
→ See §1.3 for migration pattern.
4. Is the error "StructRNA has been removed"?
YES → Reference invalidated by undo or data modification.
→ Re-fetch by name from bpy.data.
→ See §2 for patterns.
5. Is the attribute None unexpectedly?
YES → Context attribute requires specific mode or editor type.
→ Check mode before access.
→ See §1.5 for attribute requirements.
4. Version Migration Reference
4.0 Context Override Removal
Aspect
Blender 3.x
Blender 4.0+
Context override syntax
op(override_dict, ...)
REMOVED — TypeError
Recommended syntax
temp_override() (3.2+)
temp_override() (required)
bpy.context.copy() for overrides
Works but deprecated
REMOVED
temp_override() Availability
Blender Version
temp_override()
Dict overrides
3.0–3.1
NOT available
Works
3.2–3.6
Available
Works (deprecated)
4.0+
Required
REMOVED
Version Detection Pattern
# Blender 3.2+import bpy
defcall_with_override(area, region, op_func, **kwargs):
"""Call operator with context override, version-aware."""if bpy.app.version >= (3, 2, 0):
with bpy.context.temp_override(area=area, region=region):
return op_func(**kwargs)
else:
override = bpy.context.copy()
override['area'] = area
override['region'] = region
return op_func(override, **kwargs)
Note: The version-detection pattern above is provided for migration of legacy code. For new code, ALWAYS target Blender 3.2+ and use temp_override() exclusively.
5. Threading Rules
Rule: NEVER access bpy.context, bpy.ops, or modify bpy.data from background threads.
Error:
RuntimeError: can't modify blend data outside main thread
Resolution: Use bpy.app.timers.register() to schedule work on the main thread.
# Blender 3.2+import bpy
import threading
defbackground_work():
result = expensive_computation()
defapply_result():
bpy.data.objects["Cube"].location.x = result
returnNone# do not repeat
bpy.app.timers.register(apply_result)
thread = threading.Thread(target=background_work)
thread.start()
6. Quick Reference: Error Message Index
Error Message
Section
Resolution
RuntimeError: restricted context element '...'
§1.1
Use bpy.data, defer with timers
RuntimeError: Operator ... poll() failed
§1.2
Set up context, check poll()
TypeError: ... takes N positional arguments (4.0+)
§1.3
Migrate to temp_override()
ReferenceError: StructRNA of type ... has been removed
§2.1
Re-fetch by name
RuntimeError: can't modify blend data outside main thread
§5
Use bpy.app.timers.register()
AttributeError: 'NoneType' has no attribute ... on context
§1.5
Check mode before access
References
references/methods.md — Context-related API signatures
references/examples.md — Working error resolution examples
references/anti-patterns.md — Common context mistakes with corrections