Skip to content

fix(editor): guard model export against undefined geometry.index (Sentry MONOREPO-EDITOR-E0)#447

Open
anton-pascal wants to merge 1 commit into
mainfrom
fix/sentry-editor-e0
Open

fix(editor): guard model export against undefined geometry.index (Sentry MONOREPO-EDITOR-E0)#447
anton-pascal wants to merge 1 commit into
mainfrom
fix/sentry-editor-e0

Conversation

@anton-pascal

@anton-pascal anton-pascal commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Sentry: MONOREPO-EDITOR-E0 / 6H

TypeError: Cannot read properties of undefined (reading 'count') thrown during STL/OBJ/GLB model export.

Stack: settings-panel onClick → export-manager exportFn → three's STLExporter.parseObject3D.traverse.

Root cause

three r184's STLExporter does:

triangles += ( index !== null ) ? ( index.count / 3 ) : ( positionAttribute.count / 3 );

A BufferGeometry whose index was never set reports geometry.index === undefined, not null. The exporter's guard index !== null is therefore truthy for undefined, so it falls into the index.count branch and crashes reading undefined.count.

BufferGeometry semantically treats null as "no index" (non-indexed draw), which is the form all three exporters expect — but a freshly traversed/cloned mesh can carry undefined instead.

Note: the export pipeline referenced in the original Sentry report (export-manager.tsx with isMeshWithInvalidGeometry/prepareSceneForExport) has since been refactored into packages/editor/src/lib/glb-export.ts. The fix is applied there, in prepareSceneForExport, which is the shared prep path used by STL and OBJ and GLB exports.

Fix

Add a minimal, defensive normalizeGeometryIndex() pass that runs after pruneNonRenderableMeshes on the cloned export scene. For every surviving mesh, it coerces geometry.index from undefinednull:

function normalizeGeometryIndex(root: THREE.Object3D) {
  root.traverse((object) => {
    const mesh = object as THREE.Mesh
    if (!mesh.isMesh) return
    const geometry = mesh.geometry as THREE.BufferGeometry | undefined
    if (geometry && geometry.index === undefined) geometry.index = null
  })
}

Because it runs on the cloned export tree (never the live scene) and only touches the undefined case, it's safe and idempotent. STL/OBJ/GLB all benefit.

Test

Pre-existing monorepo cross-package typecheck errors (unbuilt @pascal-app/viewer/core workspaces) are unrelated to this change; no new errors reference the added code.


Note

Low Risk
Narrow defensive normalization on the export clone only, with no auth, persistence, or live-scene mutation.

Overview
Fixes STL/OBJ/GLB export crashes when a mesh’s BufferGeometry has geometry.index === undefined instead of null. three r184 exporters treat undefined as indexed geometry and read index.count, which throws during export from the settings panel.

Adds normalizeGeometryIndex() on the cloned export scene in prepareSceneForExport, immediately after pruneNonRenderableMeshes, setting geometry.index from undefinednull so non-indexed geometry matches what STL/OBJ/GLB paths expect. Only the export clone is touched; meshes that already have an index or null are unchanged.

Reviewed by Cursor Bugbot for commit e3d40d6. Bugbot is set up for automated code reviews on this repo. Configure here.

@mintlify

mintlify Bot commented Jun 27, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
pascal 🔴 Failed Jun 27, 2026, 4:06 AM

💡 Tip: Enable Workflows to automatically generate PRs for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant