
Thatopen Errors Loading
- 5 installs
- 17 repo stars
- Updated July 8, 2026
- openaec-foundation/thatopen-claude-skill-package
Helps with ai & agent building tasks.
About
thatopen-errors-loading is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- thatopen-errors-loading
- AI & Agent Building
- AI-coding skill
Thatopen Errors Loading by the numbers
- 5 all-time installs (skills.sh)
- Ranked #13,065 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Jul 26, 2026 (Skillselion catalog sync)
npx skills add https://github.com/openaec-foundation/thatopen-claude-skill-package --skill thatopen-errors-loadingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 5 |
|---|---|
| repo stars | ★ 17 |
| Last updated | July 8, 2026 |
| Repository | openaec-foundation/thatopen-claude-skill-package ↗ |
What it does
Helps with ai & agent building tasks.
Files
Loading Errors: Diagnosis & Recovery
Overview
This skill covers every failure mode that occurs when loading IFC files or initializing the ThatOpen fragment pipeline. Each error pattern maps to a specific root cause and a concrete fix.
Use this skill when:
- An IFC file fails to load or parse
- WASM initialization throws errors
- The viewer shows nothing after loading
- Fragment worker errors appear in the console
- Elements are missing from the loaded model
---
Critical Warnings
1. ALWAYS call await ifcLoader.setup() before ifcLoader.load() — skipping setup causes silent null reference failures. 2. ALWAYS call fragmentsManager.init(workerURL) before any fragment operation — the worker is required for all data operations. 3. ALWAYS match the WASM file version to the installed web-ifc npm package version — mismatches cause RuntimeError: unreachable. 4. NEVER pass a string or File object to ifcLoader.load() — it requires Uint8Array. 5. ALWAYS include a trailing slash in WASM paths — "/wasm/" not "/wasm". 6. ALWAYS serve .wasm files with MIME type application/wasm — incorrect MIME types cause CompileError. 7. ALWAYS configure COOP/COEP headers for multi-threaded WASM — SharedArrayBuffer requires cross-origin isolation. 8. NEVER assume all IFC entity types load by default — check excludedCategories if elements are missing.
---
Error Message to Fix Mapping
| Error Message / Symptom | Root Cause | Fix | Section |
|---|---|---|---|
RuntimeError: unreachable | WASM version mismatch | Match WASM files to npm version | E-01 |
CompileError: WebAssembly.instantiate() | Corrupt/wrong WASM file or MIME type | Serve .wasm as application/wasm | E-02 |
404 Not Found on web-ifc.wasm | Wrong WASM path | Fix path, add trailing slash | E-03 |
Cannot read properties of undefined on load | setup() not called | ALWAYS call await ifcLoader.setup() first | E-04 |
FragmentsManager not initialized | Worker not initialized | Call fragmentsManager.init(workerURL) | E-05 |
| Model loads but nothing renders | Missing components.init() or scene add | Call components.init(), add model.object to scene | E-06 |
| Elements missing from model | Default excludedCategories | Add missing classes via onIfcImporterInitialized | E-07 |
TypeError: data is not Uint8Array | Wrong data type passed to load() | Convert to new Uint8Array(buffer) | E-08 |
| Geometry at wrong position / z-fighting | Large world coordinates | Use COORDINATE_TO_ORIGIN: true | E-09 |
SharedArrayBuffer is not defined | Missing COOP/COEP headers | Configure server headers for cross-origin isolation | E-10 |
| Worker script 404 / CORS error | Wrong worker URL or CORS policy | Fix worker URL path, configure CORS headers | E-11 |
| Boolean operation hangs / infinite loop | Complex geometry timeout | Set BOOL_ABORT_THRESHOLD | E-12 |
Invalid IFC file or empty model | Corrupt file or wrong encoding | Validate IFC header, ensure binary fetch | E-13 |
| Tab crashes on large model | WASM memory exhaustion | Set MEMORY_LIMIT, use streaming | E-14 |
---
E-01: WASM Version Mismatch
Error: RuntimeError: unreachable or CompileError during WASM instantiation.
Cause: The .wasm binary file version does not match the installed web-ifc npm package version. The WASM binary and JavaScript API are tightly coupled — a mismatch causes undefined behavior.
Diagnostic: 1. Check installed version: npm ls web-ifc 2. Check WASM path in code — does the version in the CDN URL match? 3. If using local files, were they copied from the correct node_modules/web-ifc/ version?
Fix:
// Option A: Use autoSetWasm (recommended)
await ifcLoader.setup(); // autoSetWasm: true resolves correct version automatically
// Option B: Match CDN version to installed package
await ifcLoader.setup({
autoSetWasm: false,
wasm: {
path: "https://unpkg.com/web-ifc@0.0.77/", // MUST match npm ls web-ifc
absolute: true,
},
});Rule: NEVER hardcode a web-ifc version without verifying it matches the installed npm package. ALWAYS prefer autoSetWasm: true unless you have a specific reason for manual configuration.
---
E-02: WASM MIME Type Error
Error: CompileError: WebAssembly.instantiate(): expected magic word or similar compilation failure.
Cause: The web server serves .wasm files with the wrong MIME type (e.g., application/octet-stream or text/html for a 404 page). Browsers require application/wasm.
Diagnostic: 1. Open DevTools Network tab 2. Find the web-ifc.wasm request 3. Check the Content-Type response header
Fix (server configuration):
| Server | Configuration |
|---|---|
| Nginx | types { application/wasm wasm; } |
| Apache | AddType application/wasm .wasm |
| Express | express.static(dir, { setHeaders: (res, path) => { if (path.endsWith('.wasm')) res.type('application/wasm'); } }) |
| Vite | Handled automatically |
| Webpack | Use file-loader or copy-webpack-plugin with correct MIME |
Rule: ALWAYS verify the server serves .wasm files with Content-Type: application/wasm.
---
E-03: WASM Path Misconfiguration
Error: 404 Not Found on web-ifc.wasm or web-ifc-mt.wasm.
Cause: The WASM path does not resolve to the directory containing the WASM files. Common mistakes: missing trailing slash, wrong relative path, files not copied to public directory.
Diagnostic checklist: 1. Does the path end with /? 2. Does the directory actually contain web-ifc.wasm? 3. Is absolute: true set when using a full URL? 4. For local paths: are the files in the build output / public directory?
Fix:
// WRONG: missing trailing slash
wasm: { path: "https://unpkg.com/web-ifc@0.0.77", absolute: true }
// WRONG: relative path with absolute: true
wasm: { path: "/static/wasm/", absolute: true }
// CORRECT: CDN with trailing slash
wasm: { path: "https://unpkg.com/web-ifc@0.0.77/", absolute: true }
// CORRECT: local path (relative to document base)
wasm: { path: "/static/wasm/", absolute: false }Rule: ALWAYS include a trailing slash in WASM paths. The runtime appends web-ifc.wasm directly to this string.
---
E-04: setup() Not Called Before load()
Error: Cannot read properties of undefined, silent failure, or WASM not initialized.
Cause: IfcLoader implements the Configurable interface. WASM initialization happens inside setup(), not in the constructor or components.get().
Fix:
const ifcLoader = components.get(OBC.IfcLoader);
await ifcLoader.setup(); // ALWAYS await before load()
const model = await ifcLoader.load(data, true, "Building");Rule: ALWAYS call await ifcLoader.setup() before calling load(). This is the single most common loading failure.
---
E-05: FragmentsManager Worker Not Initialized
Error: FragmentsManager not initialized, model fails to process, or worker-related errors in console.
Cause: The fragment system requires a Web Worker for processing IFC-to-Fragments conversion. Without init(), the worker is not available.
Fix:
const fragmentsManager = components.get(OBC.FragmentsManager);
fragmentsManager.init(workerURL); // ALWAYS call before any IFC loading
const ifcLoader = components.get(OBC.IfcLoader);
await ifcLoader.setup();Diagnostic: If workerURL is wrong, you will see a 404 or CORS error. See E-11 for worker URL issues.
Rule: ALWAYS initialize FragmentsManager with a valid worker URL before any loading operations.
---
E-06: Silent Render Failure
Error: No error messages, but the viewer shows nothing (black screen or empty viewport).
Cause (check in order): 1. components.init() not called — the render loop never starts 2. model.object not added to the scene 3. Camera not pointing at the model 4. Container element has zero dimensions (0px height)
Fix:
// 1. Start render loop
components.init();
// 2. Add model to scene
const model = await ifcLoader.load(data, true, "Building");
world.scene.three.add(model.object);
// 3. Frame the camera on the model
world.camera.fit(world.scene.three.children);
// 4. Ensure container has dimensions
// CSS: #viewer { width: 100%; height: 100vh; }Diagnostic checklist:
- [ ] Is
components.init()called? - [ ] Is
model.objectadded toworld.scene.three? - [ ] Does the container element have non-zero
offsetWidthandoffsetHeight? - [ ] Is the camera positioned to see the model?
Rule: ALWAYS call components.init() and ALWAYS add model.object to the scene after loading.
---
E-07: Missing IFC Elements
Error: Model loads successfully but certain element types (spaces, openings, furnishing) are absent.
Cause: The IfcImporter has a default classes.elements set that excludes some IFC categories for performance. Common exclusions: IFCSPACE, IFCOPENINGELEMENT, IFCFLOWSEGMENT, IFCFLOWFITTING.
Fix:
ifcLoader.onIfcImporterInitialized.add((importer) => {
// Add missing categories
importer.classes.elements.add(WEBIFC.IFCSPACE);
importer.classes.elements.add(WEBIFC.IFCOPENINGELEMENT);
importer.classes.elements.add(WEBIFC.IFCFLOWSEGMENT);
});Diagnostic: Before loading, log available types after loading with ifcApi.GetAllTypesOfModel(modelID) to verify which IFC types exist in the file.
Rule: ALWAYS check the default element class set when elements are missing. NEVER assume all IFC entity types are imported by default.
---
E-08: Wrong Data Type for load()
Error: TypeError, Invalid IFC file, or empty model.
Cause: load() requires Uint8Array. Passing ArrayBuffer, string, Blob, or File directly causes failures.
Fix:
// From fetch
const buffer = await response.arrayBuffer();
const data = new Uint8Array(buffer);
// From File input
const data = new Uint8Array(await file.arrayBuffer());
// From base64
const binary = atob(base64String);
const data = new Uint8Array(binary.length);
for (let i = 0; i < binary.length; i++) data[i] = binary.charCodeAt(i);Rule: ALWAYS convert to Uint8Array before passing to load().
---
E-09: Large Coordinate / Floating-Point Issues
Error: Model appears but geometry is distorted, flickering (z-fighting), or positioned far from origin causing camera issues.
Cause: IFC models often use real-world coordinates (e.g., UTM: x=500000, y=6000000). WebGL uses 32-bit floats — at these magnitudes, precision is ~1 meter, causing visible artifacts.
Fix:
await ifcLoader.setup();
ifcLoader.settings.webIfc.COORDINATE_TO_ORIGIN = true;
const model = await ifcLoader.load(data, true, "Building");For multi-model coordination, use the coordination matrix instead:
// Load at origin, then apply coordination manually
const model = await ifcLoader.load(data, true, "Building");
// FragmentsManager handles coordination when coordinate=trueRule: ALWAYS use COORDINATE_TO_ORIGIN: true for models with large world coordinates. For multi-model federation, use the coordinate parameter in load().
---
E-10: SharedArrayBuffer Not Available
Error: SharedArrayBuffer is not defined, multi-threaded WASM fails, or falls back to single-threaded mode silently.
Cause: SharedArrayBuffer requires cross-origin isolation via HTTP headers. Without these headers, browsers disable SharedArrayBuffer for security.
Required HTTP headers:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corpFix per environment:
| Environment | Configuration |
|---|---|
| Vite | server: { headers: { 'Cross-Origin-Opener-Policy': 'same-origin', 'Cross-Origin-Embedder-Policy': 'require-corp' } } |
| Webpack devServer | Same headers in devServer.headers |
| Nginx | add_header Cross-Origin-Opener-Policy same-origin; add_header Cross-Origin-Embedder-Policy require-corp; |
| Vercel | vercel.json headers configuration |
Warning: Enabling these headers means all cross-origin resources (images, scripts, iframes) MUST have appropriate CORS headers or crossorigin attributes. This can break third-party integrations.
Rule: ALWAYS configure COOP/COEP headers for production deployments that need multi-threaded WASM. If you cannot set these headers, web-ifc falls back to single-threaded mode — functional but slower.
---
E-11: Worker Initialization Failures
Error: 404 on worker script, DOMException: Failed to construct 'Worker', or CORS errors loading worker.
Cause: The worker URL passed to fragmentsManager.init() does not resolve or is blocked by CORS policy.
Diagnostic: 1. Open DevTools Network tab — is the worker script request returning 200? 2. Is the worker URL correct relative to the document origin? 3. For cross-origin workers, is the server setting Access-Control-Allow-Origin?
Fix:
// Local worker file (most common)
fragmentsManager.init("/workers/fragment-worker.mjs");
// CDN worker (requires CORS)
fragmentsManager.init("https://cdn.example.com/workers/fragment-worker.mjs");Rule: ALWAYS verify the worker URL resolves to a valid JavaScript module. NEVER use a worker URL from a different origin without CORS headers.
---
E-12: Boolean Operation Timeout
Error: Loading hangs indefinitely on certain IFC files, browser tab becomes unresponsive.
Cause: Complex CSG (Constructive Solid Geometry) boolean operations in the IFC file cause web-ifc to enter long-running computations. This is a known limitation with certain modeling software exports.
Fix:
await ifcLoader.setup();
ifcLoader.settings.webIfc.BOOL_ABORT_THRESHOLD = 5000; // Abort after 5 seconds
ifcLoader.settings.webIfc.USE_FAST_BOOLS = true; // Faster but less accurateRule: ALWAYS set BOOL_ABORT_THRESHOLD when loading untrusted or unknown IFC files. A threshold of 5000-10000ms prevents infinite hangs while allowing most boolean operations to complete.
---
E-13: Corrupt or Invalid IFC File
Error: Invalid IFC file, empty model, or parser crash.
Diagnostic checklist: 1. Open the file in a text editor — does it start with ISO-10303-21;? 2. Was the file fetched correctly? Check response status and content length. 3. Was response.text() used instead of response.arrayBuffer()? Text decoding corrupts binary IFC data in some encodings. 4. Is the file an IFC-XML (.ifcXML) file? web-ifc only supports STEP-encoded IFC.
Fix:
// ALWAYS use arrayBuffer, never text()
const response = await fetch(url);
if (!response.ok) throw new Error(`Fetch failed: ${response.status}`);
const buffer = await response.arrayBuffer();
if (buffer.byteLength === 0) throw new Error("Empty IFC file");
const data = new Uint8Array(buffer);Rule: ALWAYS validate the response before loading. NEVER use response.text() for IFC files — ALWAYS use response.arrayBuffer().
---
E-14: WASM Memory Exhaustion
Error: Browser tab crashes, Out of memory, or RuntimeError: memory access out of bounds.
Cause: Very large IFC models (500MB+) or multiple models loaded simultaneously exhaust the WASM linear memory.
Fix:
// Set memory limit
ifcLoader.settings.webIfc.MEMORY_LIMIT = 2147483648; // 2GB
// Use streaming for large models instead of full load
// Filter unnecessary IFC classes
ifcLoader.onIfcImporterInitialized.add((importer) => {
importer.classes.elements.delete(WEBIFC.IFCFURNISHINGELEMENT);
importer.classes.elements.delete(WEBIFC.IFCSPACE);
});
// Dispose models when no longer needed
fragmentsManager.dispose();Rule: ALWAYS filter IFC classes to reduce memory when loading large models. ALWAYS dispose models that are no longer needed.
---
Diagnostic Checklist: Loading Failures
When an IFC file fails to load, work through this checklist in order:
1. Console errors? Check the browser console for specific error messages. Match to the table above. 2. WASM initialized? Is setup() called and awaited before load()? 3. Worker initialized? Is fragmentsManager.init(workerURL) called before loading? 4. WASM path correct? Does the path end with /? Do the files exist at that path? 5. Version match? Does the WASM file version match npm ls web-ifc? 6. Data type correct? Is the IFC data a Uint8Array? 7. File valid? Does it start with ISO-10303-21;? Is the response status 200? 8. Render loop active? Is components.init() called? 9. Model in scene? Is model.object added to world.scene.three? 10. Camera framed? Can the camera see the model bounds? 11. Container sized? Does the container have non-zero dimensions? 12. CORS/headers? Are COOP/COEP set for multi-threaded? Is the worker URL accessible?
---
Error Recovery Patterns
Graceful Fallback
try {
const model = await ifcLoader.load(data, true, name);
world.scene.three.add(model.object);
} catch (error) {
if (error.message.includes("unreachable")) {
console.error("WASM version mismatch — check web-ifc version");
} else if (error.message.includes("magic word")) {
console.error("WASM MIME type error — configure server for application/wasm");
} else {
console.error("IFC loading failed:", error.message);
}
}Retry with Relaxed Settings
async function loadWithFallback(data: Uint8Array, name: string) {
try {
return await ifcLoader.load(data, true, name);
} catch (firstError) {
// Retry with relaxed boolean settings
ifcLoader.settings.webIfc.USE_FAST_BOOLS = true;
ifcLoader.settings.webIfc.BOOL_ABORT_THRESHOLD = 3000;
ifcLoader.settings.webIfc.COORDINATE_TO_ORIGIN = true;
return await ifcLoader.load(data, true, name);
}
}---
Relationship to Other Skills
| Skill | Relationship |
|---|---|
thatopen-syntax-ifc-loading | Normal loading workflow. Use this errors skill when loading fails. |
thatopen-core-web-ifc | Low-level WASM engine. Error patterns E-01 through E-03 trace to web-ifc initialization. |
thatopen-core-fragments | Fragment system. Error E-05 traces to FragmentsManager initialization. |
thatopen-errors-performance | Performance-related issues (memory, speed). Complementary to E-12 and E-14. |
---
References
references/methods.md— Error types, messages, and fix patternsreferences/examples.md— Working fix examples: WASM, path, version, workerreferences/anti-patterns.md— Common mistakes that cause loading failures
Sources
- API docs: https://docs.thatopen.com/api/@thatopen/components/classes/IfcLoader
- web-ifc: https://github.com/ThatOpen/engine_web-ifc
- GitHub issues: https://github.com/ThatOpen/engine_components/issues
Loading Errors — Anti-Patterns
Common mistakes that cause IFC loading failures. Each anti-pattern includes the symptom, wrong code, correct code, and the rule to follow.
---
AP-1: Skipping the Initialization Sequence
Symptom: Multiple cascading errors, nothing works.
Wrong — missing three critical initialization steps:
const ifcLoader = components.get(OBC.IfcLoader);
const model = await ifcLoader.load(data, true, "Building");Correct — complete initialization sequence:
// 1. FragmentsManager worker
const fragmentsManager = components.get(OBC.FragmentsManager);
fragmentsManager.init(workerURL);
// 2. IfcLoader WASM
const ifcLoader = components.get(OBC.IfcLoader);
await ifcLoader.setup();
// 3. Render loop
components.init();
// 4. Load and display
const model = await ifcLoader.load(data, true, "Building");
world.scene.three.add(model.object);Rule: ALWAYS follow the initialization sequence: worker init, WASM setup, render loop, then load. Skipping any step causes failures.
---
AP-2: Hardcoding WASM CDN Version
Symptom: Works in development, breaks after npm update when web-ifc version changes.
Wrong:
// Version hardcoded — will mismatch after npm update
await ifcLoader.setup({
autoSetWasm: false,
wasm: {
path: "https://unpkg.com/web-ifc@0.0.74/",
absolute: true,
},
});Correct:
// Option A: Let autoSetWasm handle versioning (recommended)
await ifcLoader.setup();
// Option B: Dynamic version from package.json
import { version } from "web-ifc/package.json";
await ifcLoader.setup({
autoSetWasm: false,
wasm: {
path: `https://unpkg.com/web-ifc@${version}/`,
absolute: true,
},
});Rule: NEVER hardcode a web-ifc version in WASM URLs. ALWAYS use autoSetWasm: true or derive the version dynamically.
---
AP-3: Using text() Instead of arrayBuffer()
Symptom: Invalid IFC file or garbled data, even though the file is valid.
Wrong:
const response = await fetch("/model.ifc");
const text = await response.text();
const encoder = new TextEncoder();
const data = encoder.encode(text); // Encoding corruption
const model = await ifcLoader.load(data, true, "Building");Correct:
const response = await fetch("/model.ifc");
const buffer = await response.arrayBuffer();
const data = new Uint8Array(buffer); // Binary-safe
const model = await ifcLoader.load(data, true, "Building");Rule: ALWAYS use response.arrayBuffer() for IFC files. NEVER use response.text() — text encoding/decoding corrupts binary data.
---
AP-4: Ignoring setup() Return Promise
Symptom: Intermittent failures — sometimes works, sometimes WASM not ready.
Wrong:
ifcLoader.setup(); // NOT awaited — race condition
const model = await ifcLoader.load(data, true, "Building");Correct:
await ifcLoader.setup(); // ALWAYS await
const model = await ifcLoader.load(data, true, "Building");Rule: ALWAYS await the setup() call. It is an async operation that initializes WASM. Without awaiting, load() may execute before WASM is ready.
---
AP-5: No Error Handling on Load
Symptom: Application crashes on malformed IFC files instead of showing a user-friendly error.
Wrong:
const model = await ifcLoader.load(data, true, "Building");
world.scene.three.add(model.object);Correct:
try {
const model = await ifcLoader.load(data, true, "Building");
world.scene.three.add(model.object);
world.camera.fit(world.scene.three.children);
} catch (error) {
// Show user-friendly message, log details
console.error("Failed to load IFC:", error);
showNotification("The IFC file could not be loaded. It may be corrupt or unsupported.");
}Rule: ALWAYS wrap load() in a try/catch. IFC files from external sources are unreliable — NEVER let parse errors crash the application.
---
AP-6: Not Checking Container Dimensions
Symptom: Everything initializes correctly, model loads, but viewport is blank.
Wrong:
<div id="viewer"></div>
<script>
const container = document.getElementById("viewer");
world.renderer = new OBC.SimpleRenderer(components, container);
// Container has 0px height — renderer canvas is invisible
</script>Correct:
<style>
#viewer { width: 100%; height: 100vh; }
</style>
<div id="viewer"></div>
<script>
const container = document.getElementById("viewer");
// Verify dimensions before creating renderer
if (container.offsetHeight === 0) {
console.error("Viewer container has zero height");
}
world.renderer = new OBC.SimpleRenderer(components, container);
</script>Rule: ALWAYS ensure the viewer container has explicit non-zero dimensions via CSS before creating the renderer.
---
AP-7: Loading Multiple Models Without Coordination
Symptom: Models overlap or appear at completely different positions.
Wrong:
const model1 = await ifcLoader.load(data1, false, "Architecture");
const model2 = await ifcLoader.load(data2, false, "Structure");
// coordinate: false — models not alignedCorrect:
const model1 = await ifcLoader.load(data1, true, "Architecture");
const model2 = await ifcLoader.load(data2, true, "Structure");
// coordinate: true — FragmentsManager aligns via coordination matricesRule: ALWAYS pass coordinate: true when loading multiple models that need spatial alignment. The coordinate parameter triggers coordination matrix application.
---
AP-8: Forgetting Disposal
Symptom: Memory usage grows with every model load, eventually crashing the browser tab.
Wrong:
// User loads another file — old model still in memory
async function onFileSelected(file: File) {
const data = new Uint8Array(await file.arrayBuffer());
const model = await ifcLoader.load(data, true, file.name);
world.scene.three.add(model.object);
}Correct:
let currentModel: OBC.FragmentsModel | null = null;
async function onFileSelected(file: File) {
// Dispose previous model
if (currentModel) {
world.scene.three.remove(currentModel.object);
currentModel.dispose();
}
const data = new Uint8Array(await file.arrayBuffer());
currentModel = await ifcLoader.load(data, true, file.name);
world.scene.three.add(currentModel.object);
}
// On application teardown
window.addEventListener("beforeunload", () => {
components.dispose();
});Rule: ALWAYS dispose previous models before loading new ones. ALWAYS call components.dispose() on application teardown.
---
AP-9: Assuming All IFC Types Are Loaded
Symptom: "Where are my spaces / openings / MEP elements?"
Wrong:
const model = await ifcLoader.load(data, true, "Building");
// Expects IFCSPACE to be present — it is excluded by default
const classifier = components.get(OBC.Classifier);
classifier.byCategory();
// No spaces in classification treeCorrect:
ifcLoader.onIfcImporterInitialized.add((importer) => {
importer.classes.elements.add(WEBIFC.IFCSPACE);
});
const model = await ifcLoader.load(data, true, "Building");Rule: ALWAYS review the default element class set when specific element types are missing. The default set is optimized for performance, not completeness.
---
AP-10: No Timeout on Boolean Operations
Symptom: Loading hangs indefinitely on certain IFC files, no error thrown.
Wrong:
await ifcLoader.setup();
const model = await ifcLoader.load(untrustedData, true, "External");
// May hang forever on complex boolean geometryCorrect:
await ifcLoader.setup();
ifcLoader.settings.webIfc.BOOL_ABORT_THRESHOLD = 5000;
ifcLoader.settings.webIfc.USE_FAST_BOOLS = true;
const model = await ifcLoader.load(untrustedData, true, "External");Rule: ALWAYS set BOOL_ABORT_THRESHOLD when loading IFC files from untrusted or unknown sources. Without a timeout, a single complex boolean operation can hang the entire application indefinitely.
---
AP-11: Re-Parsing IFC on Every Page Load
Symptom: Slow startup (10-60 seconds) every time the page loads, even for the same model.
Wrong:
// Every visit parses the full IFC file
const data = new Uint8Array(await fetch("/model.ifc").then(r => r.arrayBuffer()));
const model = await ifcLoader.load(data, true, "Building");Correct:
// Check cache first
const cached = await loadFromIndexedDB("building.frg");
if (cached) {
const model = fragmentsManager.load(cached);
world.scene.three.add(model.object);
} else {
const data = new Uint8Array(await fetch("/model.ifc").then(r => r.arrayBuffer()));
const model = await ifcLoader.load(data, true, "Building");
world.scene.three.add(model.object);
await saveToIndexedDB("building.frg", model.export());
}Rule: ALWAYS convert IFC to Fragments binary once and cache the result. Fragment loading is orders of magnitude faster than IFC parsing. NEVER re-parse IFC files that have not changed.
---
AP-12: Using Deprecated Packages
Symptom: Import errors, missing APIs, TypeScript type conflicts.
Wrong:
import { IfcViewerAPI } from "web-ifc-viewer"; // DEPRECATED
import { IFCLoader } from "web-ifc-three"; // DEPRECATEDCorrect:
import * as OBC from "@thatopen/components"; // current (IfcLoader)
import { IfcImporter } from "@thatopen/fragments"; // current (low-level)Rule: NEVER use web-ifc-viewer or web-ifc-three. These packages are deprecated and incompatible with ThatOpen v3. ALWAYS use @thatopen/components or @thatopen/fragments.
Loading Errors — Fix Examples
Example 1: WASM Path Fix
Problem: 404 Not Found on web-ifc.wasm.
// BEFORE (broken)
await ifcLoader.setup({
autoSetWasm: false,
wasm: {
path: "https://unpkg.com/web-ifc@0.0.77", // missing trailing slash
absolute: true,
},
});
// Resolves to: https://unpkg.com/web-ifc@0.0.77web-ifc.wasm (WRONG)
// AFTER (fixed)
await ifcLoader.setup({
autoSetWasm: false,
wasm: {
path: "https://unpkg.com/web-ifc@0.0.77/", // trailing slash present
absolute: true,
},
});
// Resolves to: https://unpkg.com/web-ifc@0.0.77/web-ifc.wasm (CORRECT)---
Example 2: Version Mismatch Fix
Problem: RuntimeError: unreachable when loading IFC.
// BEFORE (broken) — installed web-ifc is 0.0.77, WASM is 0.0.74
await ifcLoader.setup({
autoSetWasm: false,
wasm: {
path: "https://unpkg.com/web-ifc@0.0.74/", // WRONG version
absolute: true,
},
});
// AFTER (fixed) — use autoSetWasm to guarantee version match
await ifcLoader.setup(); // autoSetWasm: true (default) matches npm version
// OR — match version explicitly
await ifcLoader.setup({
autoSetWasm: false,
wasm: {
path: "https://unpkg.com/web-ifc@0.0.77/", // matches npm ls web-ifc
absolute: true,
},
});---
Example 3: Complete Initialization Fix
Problem: Multiple initialization steps missing, causing cascading failures.
// BEFORE (broken) — missing init, setup, and scene add
const components = new OBC.Components();
const worlds = components.get(OBC.Worlds);
const world = worlds.create();
world.scene = new OBC.SimpleScene(components);
world.renderer = new OBC.SimpleRenderer(components, container);
world.camera = new OBC.OrthoPerspectiveCamera(components);
const ifcLoader = components.get(OBC.IfcLoader);
const model = await ifcLoader.load(data, true, "Building");
// Nothing renders, multiple errors in console
// AFTER (fixed) — correct initialization order
const components = new OBC.Components();
const worlds = components.get(OBC.Worlds);
const world = worlds.create();
world.scene = new OBC.SimpleScene(components);
world.renderer = new OBC.SimpleRenderer(components, container);
world.camera = new OBC.OrthoPerspectiveCamera(components);
components.init(); // 1. Start render loop
const fragmentsManager = components.get(OBC.FragmentsManager);
fragmentsManager.init(workerURL); // 2. Initialize worker
const ifcLoader = components.get(OBC.IfcLoader);
await ifcLoader.setup(); // 3. Initialize WASM
const model = await ifcLoader.load(data, true, "Building");
world.scene.three.add(model.object); // 4. Add to scene
world.camera.fit(world.scene.three.children); // 5. Frame camera---
Example 4: Worker URL Fix
Problem: Failed to construct 'Worker' or 404 on worker script.
// BEFORE (broken) — wrong worker path
const fragmentsManager = components.get(OBC.FragmentsManager);
fragmentsManager.init("./worker.mjs"); // relative path may not resolve
// AFTER (fixed) — use absolute path or URL constructor
// Option A: absolute path from server root
fragmentsManager.init("/workers/fragment-worker.mjs");
// Option B: construct URL relative to current module
const workerURL = new URL(
"../node_modules/@thatopen/fragments/dist/worker.mjs",
import.meta.url
).href;
fragmentsManager.init(workerURL);
// Option C: CDN URL (requires CORS)
fragmentsManager.init(
"https://unpkg.com/@thatopen/fragments@3.3.6/dist/worker.mjs"
);---
Example 5: SharedArrayBuffer / COOP-COEP Fix
Problem: SharedArrayBuffer is not defined, multi-threaded WASM unavailable.
Vite Configuration
// vite.config.ts
export default defineConfig({
server: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
},
},
});Nginx Configuration
server {
location / {
add_header Cross-Origin-Opener-Policy same-origin;
add_header Cross-Origin-Embedder-Policy require-corp;
}
}Express Configuration
app.use((req, res, next) => {
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
next();
});Fallback — Force Single-Threaded
If you cannot configure headers, force single-threaded mode:
// web-ifc direct usage
await ifcApi.Init(undefined, true); // forceSingleThread = true---
Example 6: Boolean Operation Timeout Fix
Problem: Loading hangs on specific IFC files with complex geometry.
// BEFORE (broken) — no timeout, hangs indefinitely
await ifcLoader.setup();
const model = await ifcLoader.load(complexIfcData, true, "Complex");
// Never returns...
// AFTER (fixed) — set abort threshold and fast bools
await ifcLoader.setup();
ifcLoader.settings.webIfc.BOOL_ABORT_THRESHOLD = 5000; // 5 second timeout
ifcLoader.settings.webIfc.USE_FAST_BOOLS = true; // faster algorithm
const model = await ifcLoader.load(complexIfcData, true, "Complex");
// Elements with impossible booleans are skipped, rest loads fine---
Example 7: Missing Elements Fix
Problem: HVAC elements (ducts, pipes) or spaces not visible after loading.
import * as WEBIFC from "web-ifc";
const ifcLoader = components.get(OBC.IfcLoader);
// Add missing categories BEFORE loading
ifcLoader.onIfcImporterInitialized.add((importer) => {
// MEP elements
importer.classes.elements.add(WEBIFC.IFCFLOWSEGMENT);
importer.classes.elements.add(WEBIFC.IFCFLOWFITTING);
importer.classes.elements.add(WEBIFC.IFCFLOWTERMINAL);
importer.classes.elements.add(WEBIFC.IFCFLOWCONTROLLER);
importer.classes.elements.add(WEBIFC.IFCFLOWMOVINGDEVICE);
importer.classes.elements.add(WEBIFC.IFCFLOWSTORAGEDEVICE);
importer.classes.elements.add(WEBIFC.IFCFLOWTREATMENTDEVICE);
importer.classes.elements.add(WEBIFC.IFCPIPESEGMENT);
importer.classes.elements.add(WEBIFC.IFCDUCTSEGMENT);
// Spaces (for spatial analysis)
importer.classes.elements.add(WEBIFC.IFCSPACE);
});
await ifcLoader.setup();
const model = await ifcLoader.load(data, true, "MEP-Model");---
Example 8: Large Coordinate Fix
Problem: Model geometry appears distorted, z-fighting, or camera cannot zoom properly.
// BEFORE (broken) — model at UTM coordinates
await ifcLoader.setup();
const model = await ifcLoader.load(data, true, "Building");
// Model at x=500000, y=6000000 — floating-point precision loss
// AFTER (fixed) — translate to origin
await ifcLoader.setup();
ifcLoader.settings.webIfc.COORDINATE_TO_ORIGIN = true;
const model = await ifcLoader.load(data, true, "Building");
// Model centered at origin — GPU-safe coordinates---
Example 9: Corrupt File Defensive Loading
Problem: Unknown IFC files from external sources may be corrupt or malformed.
async function safeLoadIfc(
url: string,
ifcLoader: OBC.IfcLoader,
world: OBC.World,
): Promise<OBC.FragmentsModel | null> {
// 1. Fetch with validation
const response = await fetch(url);
if (!response.ok) {
console.error(`Fetch failed: ${response.status} ${response.statusText}`);
return null;
}
const buffer = await response.arrayBuffer();
if (buffer.byteLength === 0) {
console.error("Empty file");
return null;
}
// 2. Quick header check
const header = new TextDecoder().decode(new Uint8Array(buffer, 0, 20));
if (!header.startsWith("ISO-10303-21")) {
console.error("Not a valid STEP IFC file");
return null;
}
// 3. Load with defensive settings
const data = new Uint8Array(buffer);
ifcLoader.settings.webIfc.COORDINATE_TO_ORIGIN = true;
ifcLoader.settings.webIfc.USE_FAST_BOOLS = true;
ifcLoader.settings.webIfc.BOOL_ABORT_THRESHOLD = 10000;
try {
const model = await ifcLoader.load(data, true, "External-Model");
world.scene.three.add(model.object);
world.camera.fit(world.scene.three.children);
return model;
} catch (error) {
console.error("IFC loading failed:", error.message);
return null;
}
}---
Example 10: WASM MIME Type Fix for Common Servers
Problem: CompileError: expected magic word — server returns HTML 404 page instead of WASM binary.
Express.js
import express from "express";
const app = express();
// Serve static files with correct MIME types
app.use(express.static("public", {
setHeaders: (res, filePath) => {
if (filePath.endsWith(".wasm")) {
res.setHeader("Content-Type", "application/wasm");
}
},
}));Webpack (copy WASM to output)
// webpack.config.js
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [
{
from: "node_modules/web-ifc/*.wasm",
to: "wasm/[name][ext]",
},
],
}),
],
};Vite (WASM in public directory)
# Copy WASM files to public directory
cp node_modules/web-ifc/web-ifc.wasm public/wasm/
cp node_modules/web-ifc/web-ifc-mt.wasm public/wasm/// In code
await ifcLoader.setup({
autoSetWasm: false,
wasm: { path: "/wasm/", absolute: false },
});Loading Errors — Error Types, Messages & Fix Patterns
Error Classification
Category 1: WASM Initialization Errors
These errors occur before any IFC file is opened. They indicate the WASM engine itself failed to start.
| Error Type | Message Pattern | Thrown By | Fix |
|---|---|---|---|
CompileError | WebAssembly.instantiate(): expected magic word 00 61 73 6d | Browser WASM engine | WASM file corrupt or wrong MIME type. Serve as application/wasm. |
CompileError | WebAssembly.instantiate() failed | Browser WASM engine | WASM file truncated or wrong version. Re-download or match version. |
RuntimeError | unreachable | web-ifc WASM | Version mismatch between JS API and WASM binary. |
TypeError | Cannot read properties of undefined (reading '...') | IfcLoader | setup() not called — WASM not initialized. |
Error | Failed to fetch on .wasm URL | fetch API | WASM path wrong, file missing, or network error. |
Error | 404 Not Found | HTTP server | WASM path incorrect or files not deployed. |
Category 2: IFC Parse Errors
These errors occur when opening or parsing an IFC file after WASM is initialized.
| Error Type | Message Pattern | Thrown By | Fix |
|---|---|---|---|
Error | Invalid IFC file | web-ifc | File is not valid STEP-encoded IFC. Verify file header. |
Error | Unexpected token or parser errors | web-ifc | Corrupt IFC file or encoding issue. Use arrayBuffer() not text(). |
RuntimeError | memory access out of bounds | WASM runtime | Model too large for WASM memory. Set MEMORY_LIMIT or reduce model. |
Error | Boolean operation timeout | web-ifc | Complex geometry. Set BOOL_ABORT_THRESHOLD. |
TypeError | data is not Uint8Array | IfcLoader | Wrong data type. Convert with new Uint8Array(buffer). |
Category 3: Worker Errors
These errors relate to the Web Worker used by FragmentsManager.
| Error Type | Message Pattern | Thrown By | Fix |
|---|---|---|---|
Error | FragmentsManager not initialized | FragmentsManager | Call fragmentsManager.init(workerURL) before loading. |
DOMException | Failed to construct 'Worker' | Browser Worker API | Worker URL invalid or blocked by CSP. |
Error | 404 on worker script | HTTP server | Worker URL path incorrect. |
SecurityError | CORS error on worker | Browser | Worker served from different origin without CORS headers. |
Category 4: Rendering Errors (Post-Load)
Model loads without error but visual problems occur.
| Symptom | Root Cause | Fix |
|---|---|---|
| Black / empty viewport | components.init() not called | Call components.init() to start render loop. |
| Nothing visible | model.object not added to scene | Add with world.scene.three.add(model.object). |
| Model invisible but loaded | Camera position far from model | Call world.camera.fit(world.scene.three.children). |
| Container shows nothing | Container has 0px height | Set CSS: height: 100vh or explicit pixel height. |
| Z-fighting / flickering | Large world coordinates | Use COORDINATE_TO_ORIGIN: true. |
| Geometry distorted | Floating-point precision loss | Use COORDINATE_TO_ORIGIN: true. |
| Missing elements | Excluded IFC categories | Add classes via onIfcImporterInitialized. |
---
Error Detection Methods
Checking WASM Initialization State
// IfcLoader: check isSetup
const ifcLoader = components.get(OBC.IfcLoader);
console.log("IfcLoader setup:", ifcLoader.isSetup); // boolean
// FragmentsManager: check initialized
const fm = components.get(OBC.FragmentsManager);
console.log("FragmentsManager initialized:", fm.initialized); // booleanChecking Model Load Success
const model = await ifcLoader.load(data, true, name);
// Verify model has content
console.log("Model has geometry:", model.object.children.length > 0);
// Verify model bounding box
const box = new THREE.Box3().setFromObject(model.object);
console.log("Model size:", box.getSize(new THREE.Vector3()));Checking WASM File Availability
// Pre-check WASM file before initializing
async function checkWasmAvailable(wasmPath: string): Promise<boolean> {
try {
const response = await fetch(wasmPath + "web-ifc.wasm", { method: "HEAD" });
const contentType = response.headers.get("content-type");
if (!response.ok) {
console.error(`WASM file not found: ${response.status}`);
return false;
}
if (contentType && !contentType.includes("wasm")) {
console.warn(`WASM served with wrong MIME: ${contentType}`);
}
return true;
} catch (e) {
console.error("WASM file unreachable:", e.message);
return false;
}
}---
web-ifc LogLevel Settings
Control web-ifc logging verbosity for debugging:
import { LogLevel } from "web-ifc";
// During development — see all messages
ifcApi.SetLogLevel(LogLevel.LOG_LEVEL_DEBUG);
// For troubleshooting — errors only
ifcApi.SetLogLevel(LogLevel.LOG_LEVEL_ERROR);
// Production — silent
ifcApi.SetLogLevel(LogLevel.LOG_LEVEL_OFF);When debugging loading issues, ALWAYS set LOG_LEVEL_DEBUG temporarily to capture web-ifc's internal messages.
---
LoaderSettings for Error Prevention
interface LoaderSettings {
COORDINATE_TO_ORIGIN?: boolean; // Prevents E-09 (large coordinate issues)
USE_FAST_BOOLS?: boolean; // Prevents E-12 (boolean hangs) — less accurate
BOOL_ABORT_THRESHOLD?: number; // Prevents E-12 (timeout in ms)
MEMORY_LIMIT?: number; // Prevents E-14 (memory exhaustion, in bytes)
CIRCLE_SEGMENTS_LOW?: number; // Reduces geometry detail for performance
CIRCLE_SEGMENTS_MEDIUM?: number;
CIRCLE_SEGMENTS_HIGH?: number;
}Defensive Loading Configuration
await ifcLoader.setup();
ifcLoader.settings.webIfc.COORDINATE_TO_ORIGIN = true;
ifcLoader.settings.webIfc.USE_FAST_BOOLS = true;
ifcLoader.settings.webIfc.BOOL_ABORT_THRESHOLD = 10000;
ifcLoader.settings.webIfc.MEMORY_LIMIT = 2147483648; // 2GBThis configuration prevents the most common loading failures for unknown IFC files.