Genesis-Embodied-AI/genesis-world · error · TypeError

Expected an instance of a class that inherits from TetGenMix

Error message

Expected an instance of a class that inherits from TetGenMixin, but got an instance of {type(morph).name}.

What it means

generate_tetgen_config_from_morph builds the TetGen keyword configuration dict from a morph's tetrahedralization options, and it requires the morph to be a class mixing in gs.options.morphs.TetGenMixin (which provides order, mindihedral, minratio, etc.). Passing any other morph type means those fields do not exist, so a TypeError is raised immediately with the offending class name. Callers tet_cfg and sample rely on this contract.

Source

Thrown at genesis/utils/mesh.py:1359

            uv_coords = np.vstack([uv_coords, uv_coords])

        vmesh.visual = trimesh.visual.TextureVisuals(
            uv=uv_coords,
            material=trimesh.visual.material.SimpleMaterial(
                image=Image.open(os.path.join(get_assets_dir(), texture_path)),
            ),
        )
    else:
        vmesh.visual = trimesh.visual.ColorVisuals(
            vertex_colors=np.tile(np.asarray(color, dtype=np.float32), (len(vmesh.vertices), 1))
        )

    return vmesh, mesh


def generate_tetgen_config_from_morph(morph):
    if not isinstance(morph, gs.options.morphs.TetGenMixin):
        raise TypeError(
            f"Expected an instance of a class that inherits from TetGenMixin, but got an instance of {type(morph).name}."
        )
    return dict(
        order=morph.order,
        mindihedral=morph.mindihedral,
        minratio=morph.minratio,
        nobisect=morph.nobisect,
        quality=morph.quality,
        maxvolume=morph.maxvolume,
        verbose=morph.verbose,
    )


def make_tetgen_switches(cfg):
    """Build a TetGen switches string from a config dict."""
    flags = ["p"]

    if cfg.get("quality", True):

View on GitHub (pinned to 56e4aa5d82)

Solutions

  1. Use a morph class that inherits TetGenMixin (the tetrahedralizable morphs in gs.options.morphs) so order/mindihedral/minratio fields exist.
  2. If writing a custom morph, subclass or mix in gs.options.morphs.TetGenMixin and define its fields.
  3. Check what you actually passed: print(type(morph)) at the call site and compare with the morphs exposed by gs.options.morphs.

Example fix

# before
cfg = generate_tetgen_config_from_morph(gs.morphs.Mesh(file='part.stl'))
# after
cfg = generate_tetgen_config_from_morph(gs.morphs.Tet(file='part.stl'))  # TetGenMixin-based morph
Defensive patterns

Strategy: type-guard

Validate before calling

from genesis.options import morphs
assert isinstance(morph, morphs.TetGenMixin), f'{type(morph).__name__} cannot be tetrahedralized'

Type guard

def is_tetgen_morph(morph) -> bool:
    return isinstance(morph, __import__('genesis').options.morphs.TetGenMixin)

Try / catch

try:
    cfg = generate_tetgen_config_from_morph(morph)
except TypeError as e:
    raise ValueError(f'Wrong morph for tetrahedralization: {e}') from e

Prevention

When it happens

Trigger: Passing a non-tetrahedralizable morph (e.g. gs.morphs.Mesh, gs.morphs.Box, gs.morphs.URDF) to generate_tetgen_config_from_morph (or to an API like tet_cfg/sample that forwards the morph). Using a custom morph class that does not inherit from TetGenMixin.

Common situations: Building a tetrahedral FEM/volumetric entity but passing the wrong morph type; copy-pasting an example that used TetGenMixin-based morphs (e.g. a morph with tetrahedralize options) while the actual morph is a plain Mesh; writing a custom morph and forgetting the mixin.

Understand the failure class

Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Genesis-Embodied-AI/genesis-world@56e4aa5d82 (2026-08-28). Data as JSON: /api/errors/6cdfff2baaa739bd. Report an issue: GitHub.