How to Debug Common TRELLIS.2 Issues: Artifacts and Generation Failures

Set log_level=DEBUG, validate latent vectors for NaNs, reduce dt in flow_euler.py, and visualize intermediate voxel grids with vis_utils.py to isolate whether artifacts stem from data loading, VAE collapse, flow integration instability, or renderer misconfigurations.

TRELLIS.2 is Microsoft's open-source framework for structured 3D shape generation using latent diffusion and flow matching. When debugging TRELLIS.2 artifacts and generation failures, you need to trace issues through its modular pipeline: data ingestion → latent encoding → flow/diffusion generation → rendering. This guide walks through the specific source files, diagnostic techniques, and code snippets that reveal where problems originate.

Understanding the TRELLIS.2 Pipeline and Failure Points

Each stage has distinct failure modes with recognizable symptoms. The table below maps components in the microsoft/TRELLIS.2 repository to their typical problems.

Stage Primary Module What Can Go Wrong Typical Symptoms
Data ingestion trellis2/datasets/structured_latent_shape.py Missing tensors, mismatched voxel resolutions RuntimeError on load, empty voxels
Latent encoding trellis2/trainers/vae/shape_vae.py KL-divergence collapse, overflow/underflow Loss spikes, NaN latents, uniform output
Flow/diffusion generation trellis2/pipelines/samplers/flow_euler.py Unstable ODE integration, step-size issues Sudden artifact patches, blank generations, crashes
Mesh reconstruction trellis2/renderers/voxel_renderer.py Topology errors, axis misalignment Dangling faces, holes, self-intersections
Post-processing o-voxel/o_voxel/serialize.py Format conversion errors Corrupted .ply/.glb files

Diagnosing the Four Most Common TRELLIS.2 Failure Types

1. VAE Latent Collapse Causing Blank or Noisy Output

The KL-divergence regularizer in loss_utils.py can dominate training if the learning-rate schedule is too aggressive. This produces collapsed latents that generate uniform or noisy geometry.

Diagnostic check: Inspect checkpoint tensors for near-zero values.

import torch

# Load your trained encoder

checkpoint = torch.load('path/to/checkpoint.pt')
latent_mean = checkpoint['latent.mean']
latent_logvar = checkpoint['latent.logvar']

print(f"Mean range: {latent_mean.min():.4f} to {latent_mean.max():.4f}")
print(f"Logvar mean: {latent_logvar.mean():.4f}")

# Collapsed prior indicators

if latent_mean.abs().mean() < 0.01 and latent_logvar.mean() < -5:
    print("WARNING: VAE collapse detected - KL weight too high")

Fix: Reduce KL weight, lower learning rate, or apply gradient clipping via grad_clip_utils.py.

2. Flow Integration Instability Producing Spiky Artifacts

flow_euler.py uses explicit Euler integration. When the step size dt exceeds the Lipschitz bound of the learned flow, integration diverges—creating large-scale spikes that appear as mesh artifacts.

Diagnostic check: Enable debug mode and monitor velocity norms.

from trellis2.pipelines.samplers.flow_euler import FlowEulerSampler

sampler = FlowEulerSampler(
    dt=0.01,        # Try reducing this first

    max_steps=10,   # Reduce for debugging

    debug=True      # Logs max velocity at each step

)
output = sampler(latent)

# Look for velocity_norm values that explode between steps

# Typical stable range: 0.1-10.0; values >100 indicate divergence

Fix: Decrease dt (try 0.005 or 0.001) or switch to a higher-order integrator in the sampler mix-in.

3. Voxel Grid Misalignment Creating Ghost Artifacts

data_utils.py and mesh_utils.py convert point clouds to sparse 3D grids. Off-by-one errors in voxel_origin or voxel size cause shifted geometry—thin, ghost-like artifacts after rendering.

Diagnostic check: Visualize before reconstruction.

from trellis2.utils.vis_utils import dump_voxel_grid

# Dump intermediate voxel grid before feeding to generator

dump_voxel_grid(output['voxel'], filename='debug_voxel.ply')

# Open in MeshLab/Blender to verify alignment with expected geometry

# Misalignment shows as offset or duplicated thin structures

Fix: Verify voxel_origin matches your dataset's coordinate system; use mesh_utils.align_grid if needed.

4. Renderer Tensor Layout Mismatches Causing Holes

voxel_renderer.py expects shape [B, C, D, H, W]. Swapped axes corrupt the marching-cubes algorithm, yielding holes or duplicated faces.

Diagnostic check: Validate tensor shape before extract_mesh.

from trellis2.renderers.voxel_renderer import VoxelRenderer

print(f"Voxel tensor shape: {output['voxel'].shape}")

# Expected: [batch, channels, depth, height, width]

renderer = VoxelRenderer()
mesh = renderer.render(output['voxel'])  # Fails silently if shape wrong

mesh.export('debug_mesh.glb')

Fix: Transpose with tensor.permute(0, 1, 4, 3, 2) if channels/axes are swapped; adjust iso_level (default 0.5) if faces are missing.

Step-by-Step Debugging Workflow for TRELLIS.2

Follow this sequence to isolate TRELLIS.2 generation failures from data through final output.

Step 1: Enable Verbose Logging

import logging
logging.basicConfig(level=logging.DEBUG)

# All trainers and pipelines now emit per-step loss and ODE statistics

Step 2: Validate Dataset Integrity in Isolation

from trellis2.datasets.structured_latent_shape import StructuredLatentShape

ds = StructuredLatentShape(split='train')
sample = ds[0]  # Raises immediately if source files corrupted

print(f"Voxel: {sample['voxel'].shape}, Image: {sample['image'].shape}")

Step 3: Check Latent Vector Health Post-Encoding

import torch

latent = encoder(sample['image'])
assert not torch.isnan(latent).any(), "NaNs in latent - VAE unstable"
assert not torch.isinf(latent).any(), "Infs in latent - gradient explosion"
print(f"Latent stats: mean={latent.mean():.3f}, std={latent.std():.3f}")

Step 4: Step Through Flow Sampler with Reduced Steps

from trellis2.pipelines.samplers.flow_euler import FlowEulerSampler

sampler = FlowEulerSampler(dt=0.01, max_steps=10, debug=True)
output = sampler(latent)

# Examine logged velocity norms; reduce dt if max_norm grows exponentially

Step 5: Visualize Intermediate Voxel State

from trellis2.utils.vis_utils import dump_voxel_grid

dump_voxel_grid(output['voxel'], filename='debug_voxel.ply')

# Inspect in external viewer before mesh extraction

Step 6: Render Known-Good Voxel for Comparison

from trellis2.renderers.voxel_renderer import VoxelRenderer

renderer = VoxelRenderer()
mesh = renderer.render(output['voxel'])
mesh.export('debug_mesh.glb')

# If artifacts persist here, problem is in renderer or post-processing

Quick Reference: Symptom-to-Fix Mapping

Symptom Root Cause Fix in Source
Blank output / all zeros VAE KL collapse Reduce KL weight in shape_vae.py; add clipping via grad_clip_utils.py
Spiky, jagged surfaces dt too large in Euler integration Decrease dt in flow_euler.py or use higher-order sampler
Mis-aligned ghost geometry voxel_origin mismatch Fix in data_utils.py; call mesh_utils.align_grid
Missing faces / holes Marching-cubes threshold Adjust iso_level in voxel_renderer.py
Corrupted export files Wrong tensor layout Ensure [B, C, D, H, W] before voxel_renderer.py

Key Source Files for Debugging

Component File Path
VAE trainer (shapes) trellis2/trainers/vae/shape_vae.py
Euler flow sampler trellis2/pipelines/samplers/flow_euler.py
Voxel-to-mesh renderer trellis2/renderers/voxel_renderer.py
Structured shape dataset trellis2/datasets/structured_latent_shape.py
Voxel visualization trellis2/utils/vis_utils.py
Gradient stabilization trellis2/utils/grad_clip_utils.py
Training entry point train.py
Inference example example.py

Summary

  • TRELLIS.2 artifacts typically originate in four areas: VAE latent collapse, flow integration instability, voxel grid misalignment, or renderer tensor mismatches.
  • Systematic isolation requires validating dataset integrity, checking latent vectors for NaNs/overflow, stepping through samplers with debug logging, and visualizing intermediate voxel states.
  • Critical hyperparameters to adjust: KL weight (VAE stability), dt step size (flow integration), voxel_origin (spatial alignment), and iso_level (mesh extraction quality).
  • Always verify tensor shapes before rendering—[B, C, D, H, W] is required by voxel_renderer.py.

Frequently Asked Questions

Why does TRELLIS.2 produce completely blank outputs?

Blank outputs indicate VAE latent collapse, where the KL-divergence term dominates and pushes latent distributions toward the prior. Check latent.mean and latent.logvar in your checkpoint—values near zero with very negative logvar confirm collapse. Reduce the KL weight in your training config or apply gradient clipping via grad_clip_utils.py to stabilize training.

How do I fix spiky artifacts on generated meshes?

Spiky artifacts stem from unstable flow integration in flow_euler.py. The explicit Euler step diverges when dt exceeds the flow's Lipschitz bound. Enable debug=True in the sampler and watch for exploding velocity norms. Decrease dt from 0.01 to 0.005 or 0.001, or switch to a higher-order integrator available in the sampler mix-ins.

What causes holes or missing faces in TRELLIS.2 outputs?

Holes typically result from marching-cubes threshold issues or tensor axis misalignment. First verify your voxel tensor has shape [B, C, D, H, W] before passing to voxel_renderer.py—swapped axes silently corrupt extraction. If shape is correct, lower the iso_level parameter below its default 0.5 to capture more surface geometry.

How do I debug dataset loading failures in TRELLIS.2?

Run the dataset loader in isolation using StructuredLatentShape from trellis2/datasets/structured_latent_shape.py. Access a single sample with ds[0]—this raises immediately on corrupted source files. Check that voxel resolutions match between your data and model config, and verify file paths in your dataset configuration YAML.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →