From f75cffed9f8db06ea2e07f1b0f566c529b4abffb Mon Sep 17 00:00:00 2001 From: Wassim SAMAD Date: Thu, 25 Jun 2026 16:48:39 -0400 Subject: [PATCH] fix(editor): don't crash GLB export on a material-less renderable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Baking some projects failed with "Cannot read properties of undefined (reading 'isShaderMaterial')". GLTFExporter reads material.isShaderMaterial unconditionally, so a renderable (Mesh / Line / Points) with no material crashes the export — and a non-Mesh renderable slips past both the isMesh prune check and material conversion. Guard it in pruneNonRenderableMeshes: a material-less renderable is dropped if it's a leaf, or neutralised (empty geometry + a hidden placeholder material) if it has children so its subtree survives. Post-FX disable now lets these scenes reach the exporter, which is why it surfaced. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/editor/src/lib/glb-export.ts | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/packages/editor/src/lib/glb-export.ts b/packages/editor/src/lib/glb-export.ts index bc80a2fb..7f614993 100644 --- a/packages/editor/src/lib/glb-export.ts +++ b/packages/editor/src/lib/glb-export.ts @@ -156,6 +156,11 @@ function pairClones( // plain transform node instead of a primitive. const EMPTY_GEOMETRY = new THREE.BufferGeometry() +// Hidden placeholder for a neutralised renderable that has no material: a valid +// material keeps GLTFExporter from crashing on `material.isShaderMaterial`, while +// EMPTY_GEOMETRY makes it emit a transform node instead of a primitive. +const PLACEHOLDER_MATERIAL = new THREE.MeshBasicMaterial({ visible: false }) + /** * Strip everything that must not bake into the model: * - Editor overlays on non-scene layers (gizmos, selection handles, ground @@ -182,6 +187,25 @@ function pruneNonRenderableMeshes(root: THREE.Object3D, identityNodes: Set