Install
$ agentstack add skill-impertio-studio-blender-bonsai-ifcopenshell-sverchok-claude-skill-package-ifcos-errors-patterns ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
IfcOpenShell Error Patterns and Debugging
Quick Reference
Decision Tree: Diagnosing IfcOpenShell Errors
Error occurred?
├── RuntimeError
│ ├── "entity not found in schema" → Schema mismatch (§1)
│ ├── "Failed to process shape" → Geometry failure (§4)
│ ├── Entity reference invalid → Entity was removed (§5)
│ └── Invalid STEP data → File corruption (§7)
│
├── AttributeError
│ ├── "entity has no attribute 'X'" → Wrong attribute name / wrong entity type (§2)
│ ├── NoneType has no attribute → Null return not checked (§6)
│ └── 'parent' / 'children' → IFC uses relationships, not tree attributes (§3)
│
├── TypeError
│ ├── Wrong argument type to create_entity → Type mismatch in attributes (§8)
│ ├── Expected entity, got string → Entity reference required (§8)
│ └── Missing positional argument → settings missing for geom calls (§4)
│
├── ValueError
│ ├── GUID format wrong → Use ifcopenshell.guid.new() (§9)
│ └── Coordinate scale wrong → Unit conversion missing (§10)
│
└── Silent failures (no error but wrong output)
├── Orphaned entities → Missing relationship creation (§3)
├── Duplicate property sets → Not checking existing psets (§11)
├── Invalid file → Missing OwnerHistory in IFC2X3 (§12)
└── Wrong spatial location → Missing spatial containment (§3)
Critical Warnings
- ALWAYS use
ifcopenshell.api.run()for mutations. NEVER modify entity attributes directly for relationships, spatial containment, or property sets. - ALWAYS check
model.schemabefore using schema-specific entities. Entity names differ between IFC2X3, IFC4, and IFC4X3. - ALWAYS check return values for
Nonebefore accessing attributes. Functions likeget_container(),get_type(), andcreate_shape()can returnNone. - NEVER use
model.remove()directly on products. Useifcopenshell.api.run("root.remove_product", ...)to clean up relationships. - NEVER cache entity references across file modifications. Entity wrappers become invalid after
model.remove()ormodel.undo(). - NEVER assume coordinate units. ALWAYS call
ifcopenshell.util.unit.calculate_unit_scale(model)and apply the scale factor. - ALWAYS wrap geometry processing in
try/except RuntimeError. Not all elements have processable geometry.
Error Category 1: Schema Mismatch Errors
IFC has three major schema versions with different entity names. Using an entity that does not exist in the file's schema raises RuntimeError.
# IfcOpenShell: schema-agnostic pattern
import ifcopenshell
model = ifcopenshell.open("model.ifc")
schema = model.schema # "IFC2X3", "IFC4", or "IFC4X3"
# WRONG: IfcBuiltElement only exists in IFC4X3
element = model.create_entity("IfcBuiltElement", ...)
# RuntimeError: entity 'IfcBuiltElement' not found in schema 'IFC2X3'
# CORRECT: Check schema first
if schema == "IFC4X3":
element = model.create_entity("IfcBuiltElement", ...)
else:
element = model.create_entity("IfcBuildingElementProxy", ...)
Key entity differences by schema:
| Entity/Concept | IFC2X3 | IFC4 | IFC4X3 | |---------------|--------|------|--------| | Standard wall | IfcWallStandardCase | IfcWall | IfcWall | | Building element base | IfcBuildingElement | IfcBuildingElement | IfcBuiltElement | | OwnerHistory | REQUIRED | OPTIONAL | OPTIONAL | | Door type | IfcDoorStyle | IfcDoorType | IfcDoorType | | Window type | IfcWindowStyle | IfcWindowType | IfcWindowType | | Infrastructure | Not available | Not available | IfcBridge, IfcRoad, IfcAlignment |
Error Category 2: AttributeError on Entity Attributes
IFC entity attributes use PascalCase. Using wrong case or non-existent attribute names raises AttributeError.
# WRONG: snake_case or lowercase
wall.global_id # AttributeError
wall.name # AttributeError
wall.object_type # AttributeError
# CORRECT: PascalCase as defined in IFC schema
wall.GlobalId # "3Ks0WO3qP2xhJ0wBKg$u5H"
wall.Name # "Wall 001"
wall.ObjectType # "Standard Wall"
ALWAYS use element.get_info() to discover available attributes:
info = wall.get_info()
# Returns dict: {"id": 42, "type": "IfcWall", "GlobalId": "...", "Name": "...", ...}
print(list(info.keys())) # See all attribute names
Error Category 3: Incorrect Relationship Handling
IFC uses objectified relationships (separate entities). There are NO parent/child attributes on elements.
# WRONG: IFC has no tree-style attributes
storey.parent = building # AttributeError
wall.ContainedInStructure = storey # Does NOT work as expected
# CORRECT: Use ifcopenshell.api for relationships
# Spatial hierarchy (aggregation): Project > Site > Building > Storey
ifcopenshell.api.run("aggregate.assign_object", model,
products=[storey], relating_object=building)
# Elements in spatial container (containment)
ifcopenshell.api.run("spatial.assign_container", model,
products=[wall], relating_structure=storey)
Relationship type reference:
| Relationship | API Function | Purpose | |-------------|-------------|---------| | IfcRelAggregates | aggregate.assign_object | Spatial hierarchy decomposition | | IfcRelContainedInSpatialStructure | spatial.assign_container | Element in spatial container | | IfcRelDefinesByType | type.assign_type | Element to Type assignment | | IfcRelDefinesByProperties | pset.add_pset | Property set to element | | IfcRelAssociatesMaterial | material.assign_material | Material to element | | IfcRelVoidsElement | void.add_opening | Opening in element |
Error Category 4: Geometry Processing Failures
ifcopenshell.geom.create_shape() invokes OpenCASCADE and can fail for multiple reasons.
import ifcopenshell.geom
settings = ifcopenshell.geom.settings()
settings.set(settings.USE_WORLD_COORDS, True)
# ALWAYS wrap in try/except
try:
shape = ifcopenshell.geom.create_shape(settings, element)
except RuntimeError as e:
print(f"Geometry failed for {element.is_a()} #{element.id()}: {e}")
shape = None
# ALWAYS check result before accessing geometry data
if shape is not None:
verts = shape.geometry.verts
faces = shape.geometry.faces
Common geometry failure causes:
| Cause | Symptom | Fix | |-------|---------|-----| | No Representation | RuntimeError | Check element.Representation is not None | | Missing settings argument | TypeError | Pass settings as first argument | | Spatial element (IfcSite) | RuntimeError | Filter by elements with Body representation | | Complex boolean operations | RuntimeError | Set DISABLE_OPENING_SUBTRACTIONS=True | | Corrupt geometry definition | RuntimeError | Skip element, log warning |
Check for geometry before processing:
def has_geometry(element):
"""Check if an IFC element has processable 3D geometry."""
if not hasattr(element, "Representation") or element.Representation is None:
return False
for rep in element.Representation.Representations:
if rep.RepresentationIdentifier in ("Body", "Facetation", "Tessellation"):
return True
return False
Error Category 5: Entity Invalidation After Removal
Entity wrappers are C++ pointers. After model.remove(), references become invalid.
wall = model.by_type("IfcWall")[0]
wall_id = wall.id()
wall_name = wall.Name # Works fine
model.remove(wall)
# wall is NOW INVALID: the C++ object is destroyed
# WRONG: Using invalidated reference
print(wall.Name) # RuntimeError or undefined behavior
print(wall.id()) # RuntimeError or undefined behavior
# CORRECT: Extract needed data BEFORE removal
wall_data = {"id": wall.id(), "name": wall.Name, "guid": wall.GlobalId}
ifcopenshell.api.run("root.remove_product", model, product=wall)
# Use wall_data (plain dict) from here
NEVER iterate and remove simultaneously:
# WRONG: Modifying collection while iterating
for wall in model.by_type("IfcWall"):
model.remove(wall) # Invalidates the iteration!
# CORRECT: Collect first, then remove
walls_to_remove = list(model.by_type("IfcWall"))
for wall in walls_to_remove:
ifcopenshell.api.run("root.remove_product", model, product=wall)
Error Category 6: None Return Values Not Checked
Many IfcOpenShell utility functions return None when data is not found.
import ifcopenshell.util.element
# WRONG: Assuming result is always valid
container = ifcopenshell.util.element.get_container(wall)
print(container.Name) # AttributeError if container is None!
element_type = ifcopenshell.util.element.get_type(wall)
print(element_type.Name) # AttributeError if no type assigned!
# CORRECT: ALWAYS check for None
container = ifcopenshell.util.element.get_container(wall)
if container is not None:
print(container.Name)
element_type = ifcopenshell.util.element.get_type(wall)
if element_type is not None:
print(element_type.Name)
Functions that commonly return None:
| Function | Returns None When | |----------|------------------| | get_container(element) | Element has no spatial containment | | get_type(element) | No type assigned | | get_material(element) | No material assigned | | get_psets(element).get("X") | Property set does not exist | | geom.create_shape(settings, element) | Geometry processing fails | | model.by_guid("...") | GUID not found in file |
Error Category 7: File Corruption from Direct Removal
Using model.remove() directly leaves dangling references in relationship entities.
# WRONG: Direct removal corrupts relationships
model.remove(wall)
# IfcRelContainedInSpatialStructure still references the removed wall
# IfcRelDefinesByProperties still references the removed wall
# File is NOW CORRUPTED
# CORRECT: API handles all relationship cleanup
ifcopenshell.api.run("root.remove_product", model, product=wall)
# Removes wall + cleans up:
# - Spatial containment relationships
# - Property set relationships
# - Material associations
# - Opening relationships
# - Type assignments
# - Placement (if not shared)
# - Representation (if not shared)
Error Category 8: TypeError from Wrong Attribute Types
IFC attributes have strict types. Passing wrong types raises TypeError or RuntimeError.
# WRONG: String where entity is expected
wall.ObjectPlacement = "at origin"
# RuntimeError: Expected IfcObjectPlacement, got str
# WRONG: Single entity where tuple is expected
rel.RelatedElements = wall # Expects tuple, not single entity
# CORRECT: Use proper entity references
placement = model.create_entity("IfcLocalPlacement", ...)
wall.ObjectPlacement = placement
# CORRECT: Use tuple for aggregate attributes
rel.RelatedElements = (wall1, wall2)
Error Category 9: GUID Format Errors
IFC uses 22-character base64 GUIDs, NOT standard 36-character UUIDs.
import uuid
# WRONG: Standard UUID format
wall = model.create_entity("IfcWall",
GlobalId=str(uuid.uuid4()), # 36 chars — WRONG format
Name="Wall")
# CORRECT: Use ifcopenshell.guid
wall = model.create_entity("IfcWall",
GlobalId=ifcopenshell.guid.new(), # 22 chars — correct
Name="Wall")
# BEST: Use ifcopenshell.api (auto-generates GUID)
wall = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcWall", name="Wall")
Error Category 10: Unit Conversion Errors
IFC files can use meters, millimeters, feet, or other units. NEVER assume meters.
import ifcopenshell.util.unit
# ALWAYS get the unit scale factor
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(model)
# mm file → 0.001, m file → 1.0, ft file → 0.3048
# Apply to ALL coordinates extracted from the model
raw_coords = [3500.0, 2800.0, 0.0] # From IFC file
coords_meters = [c * unit_scale for c in raw_coords]
Error Category 11: Duplicate Property Sets
Creating a property set without checking for existing ones produces duplicates.
from ifcopenshell.util.element import get_psets
# WRONG: Creates duplicate if Pset_WallCommon already exists
pset = ifcopenshell.api.run("pset.add_pset", model,
product=wall, name="Pset_WallCommon")
# CORRECT: Check first, then create or update
existing = get_psets(wall)
if "Pset_WallCommon" in existing:
pset = model.by_id(existing["Pset_WallCommon"]["id"])
else:
pset = ifcopenshell.api.run("pset.add_pset", model,
product=wall, name="Pset_WallCommon")
ifcopenshell.api.run("pset.edit_pset", model,
pset=pset, properties={"IsExternal": True})
Error Category 12: Missing OwnerHistory in IFC2X3
OwnerHistory is REQUIRED on most entities in IFC2X3 but OPTIONAL in IFC4/IFC4X3.
# WRONG: No OwnerHistory in IFC2X3
model = ifcopenshell.file(schema="IFC2X3")
wall = model.create_entity("IfcWallStandardCase",
GlobalId=ifcopenshell.guid.new(), Name="Wall")
# File is INVALID: validators will reject it
# CORRECT: Use ifcopenshell.api (handles OwnerHistory automatically)
model = ifcopenshell.file(schema="IFC2X3")
wall = ifcopenshell.api.run("root.create_entity", model,
ifc_class="IfcWallStandardCase", name="Wall")
# API creates OwnerHistory and assigns it automatically
Debugging Strategy
Step-by-step Debugging Protocol
import ifcopenshell
def debug_ifc_element(model, element):
"""Comprehensive debug output for an IFC element."""
print(f"=== Debug: {element.is_a()} #{element.id()} ===")
print(f"Schema: {model.schema}")
print(f"GlobalId: {element.GlobalId}")
print(f"Name: {element.Name}")
# 1. Check all attributes
info = element.get_info()
for key, value in info.items():
print(f" {key}: {value}")
# 2. Check spatial containment
container = ifcopenshell.util.element.get_container(element)
print(f"Container: {container.Name if container else 'NONE (PROBLEM!)'}")
# 3. Check type assignment
elem_type = ifcopenshell.util.element.get_type(element)
print(f"Type: {elem_type.Name if elem_type else 'None'}")
# 4. Check property sets
psets = ifcopenshell.util.element.get_psets(element)
print(f"Property sets: {list(psets.keys())}")
# 5. Check geometry
if hasattr(element, "Representation") and element.Representation:
reps = [r.RepresentationIdentifier
for r in element.Representation.Representations]
print(f"Representations: {reps}")
else:
print("Representations: NONE")
Common Debug Techniques
# Inspect entity type hierarchy
print(element.is_a()) # "IfcWall"
print(element.is_a("IfcRoot")) # True (checks inheritance)
# List all entities of a type
walls = model.by_type("IfcWall")
print(f"Total walls: {len(walls)}")
# Find entity by GlobalId
entity = model.by_guid("3Ks0WO3qP2xhJ0wBKg$u5H")
# Find entity by step ID
entity = model.by_id(42)
# Get inverse relationships (who references this entity?)
refs = model.get_inverse(wall)
for ref in refs:
print(f"Referenced by: {ref.is_a()} #{ref.id()}")
# Validate file units
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(model)
print(f"Unit scale to meters: {unit_scale}")
# Check file statistics
print(f"Total entities: {len(model)}")
for entity_type in ["IfcWall", "IfcSlab", "IfcColumn", "IfcBeam"]:
count = len(model.by_type(entity_type))
if count > 0:
print(f" {entity_type}: {count}")
Reference Links
- [Error Handling Methods](references/methods.md) — Exception types, validation functions, diagnostic utilities
- [Working Debug Examples](references/examples.md) — End-to-end error handling and debugging code
- [Anti-Patterns](references/anti-patterns.md) — Common IfcOpenShell mistakes with corrections
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Impertio-Studio
- Source: Impertio-Studio/Blender-Bonsai-ifcOpenshell-Sverchok-Claude-Skill-Package
- License: MIT
- Homepage: https://github.com/OpenAEC-Foundation
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.