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

> Debug TRELLIS.2 issues like artifacts and generation failures. Set log level, validate vectors, reduce dt, and visualize grids to pinpoint problems.

- Repository: [Microsoft/TRELLIS.2](https://github.com/microsoft/TRELLIS.2)
- Tags: how-to-guide
- Published: 2026-08-04

---

**Set `log_level=DEBUG`, validate latent vectors for NaNs, reduce `dt` in [`flow_euler.py`](https://github.com/microsoft/TRELLIS.2/blob/main/flow_euler.py), and visualize intermediate voxel grids with [`vis_utils.py`](https://github.com/microsoft/TRELLIS.2/blob/main/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](https://github.com/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`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/datasets/structured_latent_shape.py) | Missing tensors, mismatched voxel resolutions | `RuntimeError` on load, empty voxels |
| **Latent encoding** | [`trellis2/trainers/vae/shape_vae.py`](https://github.com/microsoft/TRELLIS.2/blob/main/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`](https://github.com/microsoft/TRELLIS.2/blob/main/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`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/renderers/voxel_renderer.py) | Topology errors, axis misalignment | Dangling faces, holes, self-intersections |
| **Post-processing** | [`o-voxel/o_voxel/serialize.py`](https://github.com/microsoft/TRELLIS.2/blob/main/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`](https://github.com/microsoft/TRELLIS.2/blob/main/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.

```python
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`](https://github.com/microsoft/TRELLIS.2/blob/main/grad_clip_utils.py).

### 2. Flow Integration Instability Producing Spiky Artifacts

[`flow_euler.py`](https://github.com/microsoft/TRELLIS.2/blob/main/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.

```python
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`](https://github.com/microsoft/TRELLIS.2/blob/main/data_utils.py) and [`mesh_utils.py`](https://github.com/microsoft/TRELLIS.2/blob/main/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.

```python
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`](https://github.com/microsoft/TRELLIS.2/blob/main/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`.

```python
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

```python
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

```python
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

```python
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

```python
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

```python
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

```python
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`](https://github.com/microsoft/TRELLIS.2/blob/main/shape_vae.py); add clipping via [`grad_clip_utils.py`](https://github.com/microsoft/TRELLIS.2/blob/main/grad_clip_utils.py) |
| Spiky, jagged surfaces | `dt` too large in Euler integration | Decrease `dt` in [`flow_euler.py`](https://github.com/microsoft/TRELLIS.2/blob/main/flow_euler.py) or use higher-order sampler |
| Mis-aligned ghost geometry | `voxel_origin` mismatch | Fix in [`data_utils.py`](https://github.com/microsoft/TRELLIS.2/blob/main/data_utils.py); call `mesh_utils.align_grid` |
| Missing faces / holes | Marching-cubes threshold | Adjust `iso_level` in [`voxel_renderer.py`](https://github.com/microsoft/TRELLIS.2/blob/main/voxel_renderer.py) |
| Corrupted export files | Wrong tensor layout | Ensure `[B, C, D, H, W]` before [`voxel_renderer.py`](https://github.com/microsoft/TRELLIS.2/blob/main/voxel_renderer.py) |

## Key Source Files for Debugging

| Component | File Path |
|-----------|-----------|
| VAE trainer (shapes) | [`trellis2/trainers/vae/shape_vae.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/trainers/vae/shape_vae.py) |
| Euler flow sampler | [`trellis2/pipelines/samplers/flow_euler.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/pipelines/samplers/flow_euler.py) |
| Voxel-to-mesh renderer | [`trellis2/renderers/voxel_renderer.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/renderers/voxel_renderer.py) |
| Structured shape dataset | [`trellis2/datasets/structured_latent_shape.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/datasets/structured_latent_shape.py) |
| Voxel visualization | [`trellis2/utils/vis_utils.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/utils/vis_utils.py) |
| Gradient stabilization | [`trellis2/utils/grad_clip_utils.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/utils/grad_clip_utils.py) |
| Training entry point | [`train.py`](https://github.com/microsoft/TRELLIS.2/blob/main/train.py) |
| Inference example | [`example.py`](https://github.com/microsoft/TRELLIS.2/blob/main/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`](https://github.com/microsoft/TRELLIS.2/blob/main/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`](https://github.com/microsoft/TRELLIS.2/blob/main/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`](https://github.com/microsoft/TRELLIS.2/blob/main/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`](https://github.com/microsoft/TRELLIS.2/blob/main/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`](https://github.com/microsoft/TRELLIS.2/blob/main/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.