# Ifc Errors Broken References

> 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

- Skill: `impertio-studio/ifc-errors-broken-references` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add impertio-studio/ifc-errors-broken-references`
- Raw SKILL.md: https://api.skillmd.com/api/skills/impertio-studio/ifc-errors-broken-references/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: Impertio-Studio (https://skillmd.com/u/impertio-studio)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/impertio-studio/ifc-errors-broken-references

---


# 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) :

1. 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.
2. **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 :
1. The target instance was lost : restore or re-create it with a correct `#id`.
2. The reference is spurious : remove the reference, or set the slot to `$` if
   the attribute is OPTIONAL.
3. 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)

- IfcObjectDefinition (INVERSE block) : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcObjectDefinition.htm
- IfcObject (IsDefinedBy, IsTypedBy) : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcObject.htm
- IfcElement (ContainedInStructure) : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcElement.htm
- IfcRelContainedInSpatialStructure : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelContainedInSpatialStructure.htm
- IfcRelAssociatesMaterial : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelAssociatesMaterial.htm
- IfcRelDefinesByProperties : https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelDefinesByProperties.htm
- ISO 10303-21 (STEP `#id` grammar, forward references) : https://en.wikipedia.org/wiki/ISO_10303-21
- IFC2x3 TC1 specification : https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/
- IFC4 ADD2 TC1 specification : https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/

