| name | ifc-errors-broken-references |
| description | Use when an IFC file has a reference that points nowhere, a parser crashes on an unresolved #id, or an element silently disappears from a downstream tool (no material, no property set, no spatial location) even though the file is schema-valid. Prevents treating a dangling #id and a missing INVERSE link as the same bug, trusting a "valid" verdict to mean the model is complete, and creating a relationship with the Relating and Related roles swapped. Covers the reference-graph nature of the STEP instance model, dangling and wrong-typed #id references, missing IfcRel* relationship entities, why a missing INVERSE attribute is a silent failure, detection scans, and fixes, across IFC2x3, IFC4 and IFC4.3 including the IfcBuildingElement to IfcBuiltElement rename. Keywords: dangling reference, broken #id, unresolved reference, missing INVERSE link, IfcRelContainedInSpatialStructure, IfcRelAssociatesMaterial, IfcRelDefinesByProperties, orphan element, element has no material, element has no property set, element not in spatial structure, ContainedInStructure, HasAssociations, IsDefinedBy, wrong-typed reference, reference graph, forward reference, "object not found", "by_id failed", "nothing shows for this wall", "valid file but element missing", how do I fix a broken reference, what is a dangling reference in IFC.
|
| license | MIT |
| compatibility | Designed for Claude Code. Requires IFC IFC2x3, IFC4, IFC4.3. |
| metadata | {"author":"OpenAEC-Foundation","version":"1.0"} |
IFC Broken References
Diagnose and fix two distinct reference faults in an IFC instance file : a
dangling reference (a #id token that resolves to nothing or to the wrong
entity type) and a missing INVERSE link (a relationship entity that was
never created, so an element has no material, no property set, or no spatial
location). The first is a hard failure a parser or validator catches. The
second is a silent failure no schema check ever reports.
For STEP syntax and header errors see ifc-errors-encoding-issues. For
EXPRESS WHERE and global-rule violations see ifc-errors-schema-validation.
For loading and traversing a model see ifc-impl-reading-parsing.
Quick Reference
An IFC file is a reference graph
A STEP Physical File (.ifc) is a flat list of numbered instances. Every line
defines one instance : #id=ENTITY(attr,attr,...). Any attribute that names
another instance does so with a #id token. The whole file is therefore a
directed graph : instances are nodes, #id tokens are edges.
#42=IFCWALL('1a2B...',#5,'Wall-01',$,$,#88,#120,'TAG-42',$);
^^ ^^^ ^^^^
OwnerHistory ObjectPlacement, Representation
Two facts drive every bug in this skill (verified, ISO 10303-21) :
- References may be forward (the referenced
#id is defined later in the
file) or backward. A conformant reader MUST index the entire file before
resolving any reference. NEVER assume a reference target appears earlier.
- Only explicit attributes are serialized.
INVERSE and DERIVE
attributes are absent from every encoding ; a reader recomputes them by
indexing the forward references. A relationship therefore exists ONLY if its
IfcRel* instance was written. No instance, no link.
Two fault classes : never conflate them
| Fault | What it is | Detected by | Severity |
|---|
| Dangling reference | A #id token resolves to no instance, or to an instance of the wrong entity type | Parser (crash / by_id error) or schema type check | HARD : file rejected or load aborts |
| Missing INVERSE link | The IfcRel* entity that would wire an element to a material / Pset / container was never created | Nothing : every INVERSE attribute has lower bound 0 | SILENT : file is schema-valid, element vanishes downstream |
ALWAYS classify the fault before fixing it. A dangling reference is a broken
edge. A missing INVERSE link is a missing node. They have opposite symptoms and
opposite fixes.
Why a missing link is silent
INVERSE attributes are computed back-references. Their cardinality is what
makes a missing link invisible (verified verbatim from the IFC4.3
IfcObjectDefinition, IfcObject and IfcElement schema pages) :
IfcObjectDefinition.HasAssociations : SET [0:?] OF IfcRelAssociates FOR RelatedObjects
IfcObjectDefinition.Decomposes : SET [0:1] OF IfcRelAggregates FOR RelatedObjects
IfcObject.IsDefinedBy : SET [0:?] OF IfcRelDefinesByProperties FOR RelatedObjects
IfcObject.IsTypedBy : SET [0:1] OF IfcRelDefinesByType FOR RelatedObjects
IfcElement.ContainedInStructure : SET [0:1] OF IfcRelContainedInSpatialStructure FOR RelatedElements
Every lower bound is 0. A wall with zero materials, zero property sets and
zero spatial container is perfectly valid EXPRESS. The schema cannot require a
link, because it cannot know which model needs which link. So a missing
material, a missing Pset, or an orphan element passes validation and only
surfaces when a quantity take-off, a schedule, or a viewer traversal returns
nothing for that element.
Symptom to fault map
| Symptom | Fault | Section |
|---|
Parser raises "instance #N not found" / by_id fails | Dangling reference | Pattern 1 |
Validator reports a type or WHERE-rule error on an attribute | Wrong-typed reference | Pattern 2 |
| Element is in the file but absent from spatial tree / viewer | Missing IfcRelContainedInSpatialStructure | Pattern 3 |
| Element shows no material, schedule column is empty | Missing IfcRelAssociatesMaterial | Pattern 4 |
| Element has no properties, Pset query returns empty | Missing IfcRelDefinesByProperties | Pattern 5 |
Decision Trees
Classify the fault
A reference looks wrong.
|
+-- Does the target #id exist as a defined instance in the file?
| NO -> DANGLING REFERENCE (hard). Go to Pattern 1.
| YES -> continue.
|
+-- Is the target instance of a type the attribute's EXPRESS type allows?
| NO -> WRONG-TYPED REFERENCE (hard). Go to Pattern 2.
| YES -> the reference itself is fine.
|
+-- Is a relationship MISSING entirely (element has no material / Pset /
container, and you expected one)?
YES -> MISSING INVERSE LINK (silent). Go to Pattern 3, 4 or 5.
NO -> the model is reference-complete for this concern.
A mandatory attribute shows $
An attribute slot holds $ (unset).
|
+-- Is the attribute OPTIONAL in the EXPRESS schema for this version?
| YES -> $ is legal. Not a fault.
| NO -> continue.
|
+-- $ in a mandatory slot = a missing required reference.
-> This is a schema error, NOT a dangling reference.
-> Fix: supply the required #id. See ifc-errors-schema-validation.
NEVER confuse $ (a legal token meaning "no value") with a dangling #id (an
illegal token meaning "value points nowhere"). * is a third token : a derived
attribute slot whose value is computed, never a reference fault.
Element missing downstream but file is "valid"
A tool (viewer, QTO, schedule) shows nothing for element X,
yet validation passed.
|
+-- ContainedInStructure empty? -> orphan element. Pattern 3.
+-- HasAssociations has no IfcRelAssociatesMaterial? -> no material. Pattern 4.
+-- IsDefinedBy has no IfcRelDefinesByProperties? -> no Pset. Pattern 5.
+-- Decomposes empty on a spatial element (not IfcProject)?
-> spatial element detached from the tree. Pattern 3.
Patterns
Pattern 1 : Detect and fix a dangling reference
A dangling reference is a #id token with no matching #id= definition. ALWAYS
detect it by index-and-diff : build the set of all defined ids, build the
set of all referenced ids, and subtract.
ALWAYS index the whole file first : a forward reference is legal, so a #id
seen before its definition is NOT dangling. Only a #id absent from the
complete definition set is dangling.
Fix options, in order of preference :
- The target instance was lost : restore or re-create it with a correct
#id.
- The reference is spurious : remove the reference, or set the slot to
$ if
the attribute is OPTIONAL.
- NEVER point the reference at an arbitrary surviving instance to silence the
parser : a wrong target is a wrong-typed reference, a worse bug.
See references/examples.md Example 1 for a raw-text scan and an ifcopenshell
scan. See references/methods.md for the token grammar.
Pattern 2 : Detect a wrong-typed reference
The #id exists, but the instance it names is not of a type the attribute
accepts. Example : IfcProduct.ObjectPlacement must reference an
IfcObjectPlacement (in practice IfcLocalPlacement or IfcGridPlacement). A
#id pointing at an IfcCartesianPoint is wrong-typed.
A wrong-typed reference is a HARD failure : it breaks the EXPRESS attribute
type, and a schema validator reports a type error or a WHERE-rule break. ALWAYS
fix it by repointing the reference at an instance of the correct type, or by
creating the missing correctly-typed instance. See references/examples.md
Example 2.
Pattern 3 : Fix an orphan element (missing spatial container)
Every physical element ALWAYS belongs to exactly one spatial level through one
IfcRelContainedInSpatialStructure. If ContainedInStructure is empty the
element is an orphan : invisible to spatial traversal, FM and quantity take-off.
Fix : create one IfcRelContainedInSpatialStructure whose RelatingStructure
is the spatial element (storey, space) and whose RelatedElements includes the
element. NEVER add the element to two such relationships : WHERE rule WR31
forbids more than one containment per element. See references/examples.md
Example 3.
Spatial elements themselves attach to the tree through IfcRelAggregates
(Decomposes inverse), not IfcRelContainedInSpatialStructure. A storey with
an empty Decomposes is detached from its building. For the full spatial-tree
rules see ifc-errors-spatial-structure.
Pattern 4 : Fix a missing material association
An element with an empty HasAssociations (or one holding no
IfcRelAssociatesMaterial) has no material : material schedules and
material-based take-off return nothing for it.
Fix : create one IfcRelAssociatesMaterial whose RelatingMaterial is an
IfcMaterial (or IfcMaterialLayerSet, IfcMaterialProfileSet,
IfcMaterialConstituentSet) and whose RelatedObjects includes the element or
its type. One IfcRelAssociatesMaterial MAY serve many elements via its
RelatedObjects set. See references/examples.md Example 4.
Pattern 5 : Fix a missing property set
An element with an empty IsDefinedBy (holding no IfcRelDefinesByProperties)
carries no occurrence property sets. Property queries return empty.
Fix : create one IfcRelDefinesByProperties whose RelatingPropertyDefinition
is an IfcPropertySet and whose RelatedObjects includes the element. Note the
type-versus-occurrence split : property sets on an IfcTypeObject are reached
through IfcTypeObject.HasPropertySets, NOT through IfcRelDefinesByProperties.
Check both the occurrence and its type before declaring a Pset missing. See
references/examples.md Example 5.
Version Notes
| Concern | IFC2x3 | IFC4 / IFC4.3 |
|---|
Property-set inverse on IfcObject | IsDefinedBy : SET OF IfcRelDefines covers BOTH type and properties | IsDefinedBy is properties only ; IsTypedBy split out for the type link (IFC4+) |
RelatingStructure type of IfcRelContainedInSpatialStructure | IfcSpatialStructureElement | IfcSpatialElement (IFC4.3) ; IfcSpatialStructureElement (IFC4) |
Element supertype below which ContainedInStructure is defined | IfcElement (under IfcBuildingElement) | IfcElement (under IfcBuiltElement in IFC4.3 ; IfcBuildingElement in IFC4) |
Surface-feature inverse HasSurfaceFeatures | absent | IFC4.3 only |
IfcBuildingElement (IFC2x3, IFC4) was renamed to IfcBuiltElement and
made non-abstract in IFC4.3. NEVER write IfcBuildingElement in an IFC4.3
file ; the name returns HTTP 404 in the IFC4.3 schema. The ContainedInStructure
inverse is unaffected by the rename because it is declared on IfcElement,
which exists under both names.
Reference Links
references/methods.md : the #id token grammar, the $ / * tokens, the
full INVERSE signatures with cardinalities, and the relationship-entity
attribute signatures used to fix each fault.
references/examples.md : verified detection scans (raw text and
ifcopenshell) and the STEP for each fix.
references/anti-patterns.md : the mistakes that create or hide broken
references, and why each fails.
Official sources (verified 2026-05-20)