Use when validating, auditing, or verifying IFC model quality in Bonsai projects. Provides systematic checks for spatial hierarchy completeness, property set compliance, geometry validity, classification correctness, and IDS (Information Delivery Specification) conformance using ifctester. Prevents shipping models with missing spatial containment or incomplete property sets. Keywords: IFC validation, audit, quality check, spatial hierarchy, property set, IDS, ifctester, model quality, Bonsai validation, compliance, check my IFC file, is my model correct, find errors.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
Use when validating, auditing, or verifying IFC model quality in Bonsai projects. Provides systematic checks for spatial hierarchy completeness, property set compliance, geometry validity, classification correctness, and IDS (Information Delivery Specification) conformance using ifctester. Prevents shipping models with missing spatial containment or incomplete property sets. Keywords: IFC validation, audit, quality check, spatial hierarchy, property set, IDS, ifctester, model quality, Bonsai validation, compliance, check my IFC file, is my model correct, find errors.
license
MIT
compatibility
Designed for Claude Code. Requires Blender with Bonsai addon.
Requests validation, auditing, checking, or verification of an IFC model
Asks to run quality assurance (QA) on a Bonsai project
Needs to verify IFC compliance before model handover or delivery
Wants to check an IFC model against an IDS specification
Asks to diagnose structural or data issues in an IFC file
Requests a pre-submission or pre-export quality check
Needs to verify spatial hierarchy, property completeness, or classification correctness
Critical Warnings
ALWAYS run validation in the prescribed order: Schema → Spatial → Properties → Geometry → Classification → IDS. Schema failures invalidate all subsequent checks.
ALWAYS check model.schema before applying version-specific validation logic. IFC2X3, IFC4, and IFC4X3 have different entity sets and rules.
NEVER assume a model is valid because ifcopenshell.validate.validate() completes without exception. Validation issues are logged, NOT raised. Use json_logger or LogDetectionHandler to detect issues.
ALWAYS use ifcopenshell.util.element.get_psets() for property reading. NEVER traverse IsDefinedBy relationships manually.
ALWAYS use ifctester for IDS validation. ifcopenshell.validate checks schema compliance only — it does NOT check project-specific requirements.
NEVER confuse schema validation with IDS validation. Schema validation verifies IFC file structure per EXPRESS schema. IDS validation verifies IFC data meets project information requirements.
ALWAYS access the IFC model via tool.Ifc.get() inside Bonsai or IfcStore.get_file(). NEVER access IfcStore.file directly.
ALWAYS guard against None return from IfcStore.get_file() before running any validation.
Validation Process: Execution Order
Execute these phases sequentially. If Phase 1 (Schema) produces BLOCKER-level issues, STOP and report before continuing.
Phase 1: Schema Validation
Validates IFC file structure against the EXPRESS schema definition.
import ifcopenshell
import ifcopenshell.validate
model = ifcopenshell.open("project.ifc") # or tool.Ifc.get() inside Bonsai# Step 1: Basic schema validation
json_log = ifcopenshell.validate.json_logger()
ifcopenshell.validate.validate(model, json_log)
schema_errors = [s for s in json_log.statements if s["level"] == "ERROR"]
schema_warnings = [s for s in json_log.statements if s["level"] == "WARNING"]
# Step 2: If basic passes, run EXPRESS WHERE rules (10-100x slower)ifnot schema_errors:
json_log_express = ifcopenshell.validate.json_logger()
ifcopenshell.validate.validate(model, json_log_express, express_rules=True)
Severity mapping:
Condition
Severity
Any ERROR in json_log.statements
BLOCKER
Any WARNING in json_log.statements
WARNING
EXPRESS WHERE rule violation
WARNING
Clean schema validation pass
INFO (proceed)
Phase 2: Spatial Hierarchy Validation
Verifies the required IFC spatial structure exists and all elements are contained.
import ifcopenshell
import ifcopenshell.util.element
defvalidate_spatial_hierarchy(model):
errors = []
schema = model.schema
# 2a: Verify IfcProject exists (exactly one)
projects = model.by_type("IfcProject")
iflen(projects) != 1:
errors.append(("BLOCKER", f"Expected 1 IfcProject, found {len(projects)}"))
return errors
# 2b: Verify IfcSite exists
sites = model.by_type("IfcSite")
iflen(sites) == 0:
errors.append(("BLOCKER", "No IfcSite found"))
# 2c: Verify IfcBuilding exists
buildings = model.by_type("IfcBuilding")
iflen(buildings) == 0:
errors.append(("BLOCKER", "No IfcBuilding found"))
# 2d: Verify IfcBuildingStorey exists (standard buildings)
storeys = model.by_type("IfcBuildingStorey")
iflen(storeys) == 0andlen(buildings) > 0:
errors.append(("WARNING", "No IfcBuildingStorey found"))
# 2e: Verify spatial decomposition chain# IFC4X3 allows IfcFacility / IfcFacilityPart as alternativesif schema == "IFC4X3":
facilities = model.by_type("IfcFacility")
iflen(buildings) == 0andlen(facilities) == 0:
errors.append(("BLOCKER", "No IfcBuilding or IfcFacility found"))
# 2f: Check all physical elements have spatial containmentfor element in model.by_type("IfcElement"):
container = ifcopenshell.util.element.get_container(element)
if container isNone:
errors.append((
"WARNING",
f"#{element.id()}{element.is_a()} '{element.Name}': "f"Not contained in any spatial element"
))
return errors
Severity mapping:
Condition
Severity
Missing IfcProject or count != 1
BLOCKER
Missing IfcSite
BLOCKER
Missing IfcBuilding (IFC2X3/IFC4)
BLOCKER
Missing IfcBuilding AND IfcFacility (IFC4X3)
BLOCKER
Missing IfcBuildingStorey
WARNING
IfcElement without spatial containment
WARNING
Spatial hierarchy complete
INFO
Phase 3: Property Set Compliance
Validates property sets exist and contain required properties.
import ifcopenshell.util.element
defvalidate_property_compliance(model, requirements):
"""
requirements: dict of {ifc_class: {pset_name: [prop_names]}}
Example: {"IfcWall": {"Pset_WallCommon": ["IsExternal", "FireRating"]}}
"""
errors = []
for ifc_class, pset_reqs in requirements.items():
elements = model.by_type(ifc_class)
for element in elements:
psets = ifcopenshell.util.element.get_psets(element)
for pset_name, required_props in pset_reqs.items():
if pset_name notin psets:
errors.append((
"WARNING",
f"#{element.id()}{element.is_a()} '{element.Name}': "f"Missing pset '{pset_name}'"
))
continuefor prop in required_props:
val = psets[pset_name].get(prop)
if val isNone:
errors.append((
"WARNING",
f"#{element.id()}{element.Name}: "f"Missing {pset_name}.{prop}"
))
return errors
Standard property requirements by element type:
IFC Class
Standard Pset
Key Properties
IfcWall
Pset_WallCommon
IsExternal, LoadBearing, FireRating
IfcSlab
Pset_SlabCommon
IsExternal, LoadBearing
IfcDoor
Pset_DoorCommon
IsExternal, FireRating
IfcWindow
Pset_WindowCommon
IsExternal, ThermalTransmittance
IfcBeam
Pset_BeamCommon
LoadBearing
IfcColumn
Pset_ColumnCommon
LoadBearing
IfcSpace
Pset_SpaceCommon
IsExternal, GrossPlannedArea
Severity mapping:
Condition
Severity
Standard pset completely missing on element
WARNING
Required property missing from existing pset
WARNING
Property value is empty/null
INFO
All required properties present
INFO
Phase 4: Geometry Validation
Checks geometry representations exist and are valid.
defvalidate_geometry(model):
errors = []
for element in model.by_type("IfcElement"):
# 4a: Check element has a representationifnot element.Representation:
errors.append((
"WARNING",
f"#{element.id()}{element.is_a()} '{element.Name}': "f"No geometry representation"
))
continue# 4b: Check representation has itemsfor rep in element.Representation.Representations:
ifnot rep.Items orlen(rep.Items) == 0:
errors.append((
"WARNING",
f"#{element.id()}{element.Name}: "f"Empty representation '{rep.RepresentationIdentifier}'"
))
# 4c: Check for placement consistencyfor element in model.by_type("IfcElement"):
if element.ObjectPlacement isNone:
errors.append((
"INFO",
f"#{element.id()}{element.is_a()} '{element.Name}': "f"No IfcLocalPlacement"
))
return errors
Severity mapping:
Condition
Severity
IfcElement with no Representation at all
WARNING
Empty representation (no Items)
WARNING
Missing IfcLocalPlacement
INFO
Valid geometry present
INFO
Phase 5: Classification Validation
Verifies classification references (Uniclass, OmniClass, NL-SfB, etc.) are present and correctly structured.
import ifcopenshell.util.classification
defvalidate_classifications(model, required_system=None):
errors = []
# 5a: Check classification systems exist
systems = model.by_type("IfcClassification")
iflen(systems) == 0:
errors.append(("INFO", "No classification system referenced in model"))
return errors
if required_system:
system_names = [s.Name for s in systems]
if required_system notin system_names:
errors.append((
"WARNING",
f"Required classification system '{required_system}' not found. "f"Available: {system_names}"
))
# 5b: Check elements have classification references
classified_count = 0
unclassified = []
for element in model.by_type("IfcElement"):
refs = ifcopenshell.util.classification.get_references(element)
if refs:
classified_count += 1else:
unclassified.append(element)
total = len(model.by_type("IfcElement"))
if unclassified:
errors.append((
"INFO",
f"{len(unclassified)}/{total} elements lack classification references"
))
# 5c: Validate classification reference formatfor ref in model.by_type("IfcClassificationReference"):
ifnot ref.Identification andnot ref.ItemReference:
errors.append((
"WARNING",
f"#{ref.id()} IfcClassificationReference: "f"Missing Identification/ItemReference"
))
return errors