# How to Debug Sampling Failures or Artifacts in TRELLIS.2 Generated Geometry

> Debug TRELLIS.2 sampling failures and artifacts. Learn to enable verbose sampling, inspect tensors, and validate conditioning data to fix empty outputs and structural issues.

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

---

**Enable verbose sampling, inspect intermediate tensors from the Euler integrator, and validate conditioning data shapes to isolate the root cause of empty outputs or structural artifacts.**

TRELLIS.2 is Microsoft's open-source framework for reconstructing and generating high-quality 3D geometry using flow-matching and VAE models. When you encounter empty meshes, noisy textures, or structural deformities during inference, the issue typically originates in the sampling pipeline's configuration, conditioning inputs, or Euler integration hyperparameters.

## Understanding the Core Sampling Pipeline

The generation process relies on the **`FlowEulerSampler`** class in **[`trellis2/pipelines/samplers/flow_euler.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/pipelines/samplers/flow_euler.py)**. This sampler implements an Euler integrator that iteratively refines a noisy tensor `x_t` into a clean output `x_0` over a series of discrete steps. The sampler returns an `edict` object containing intermediate predictions (`pred_x_t`, `pred_x_0`) and the final denoised samples.

According to the Microsoft/TRELLIS.2 source code, sampling failures cascade from five primary layers: sampler configuration, conditional inputs, model loading, data pipeline integrity, and post-processing rendering.

## Common Sources of Sampling Failures

### Sampler Configuration Errors

Improper hyperparameters in the flow-matching schedule cause the most common artifacts. Ensure **`sigma_min`** is set between `0` and `1.0` (inclusive of 0, exclusive of 1) to maintain noise schedule stability. If geometry appears overly coarse or collapses to a single shape, increase the **`steps`** parameter (e.g., from 50 to 100). For classifier-free guidance, keep **`guidance_strength`** and **`guidance_interval`** within the range `[0, 1]` to prevent semantic divergence.

### Conditional Input Mismatches

The `cond` and `neg_cond` tensors must match the model's expected channel dimensions. Mismatched shapes trigger silent broadcasting bugs that manifest as color bleeding or empty meshes. Always verify that text embeddings or image conditioning are correctly pre-processed by the dataset pipeline before reaching the sampler's `sample()` method.

### Model Checkpoint Incompatibility

Confirm that loaded checkpoints match the **FlowEulerSampler** architecture, which expects flow-matching models outputting velocity `v`. When loading on CPU-only machines, use `torch.load(..., map_location='cpu')` to prevent device mismatch errors and NaN propagation in intermediate tensors.

### Data Pipeline Corruption

Inspect input voxel or mesh representations in **`trellis2/datasets/`** and **[`trellis2/utils/mesh_utils.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/utils/mesh_utils.py)** for holes or non-manifold edges. Run [`data_toolkit/voxelize_pbr.py`](https://github.com/microsoft/TRELLIS.2/blob/main/data_toolkit/voxelize_pbr.py) on problematic assets and visualize the voxel grid using **`vis_utils.plot_voxels`**. Corrupted input representations propagate directly to the final output.

### Renderer and Post-Processing Issues

Ensure the renderer receives the correct data type (`Mesh`, `Voxel`, or `MeshWithPbrMaterial`). After sampling, recompute vertex normals using **`mesh_utils.compute_normals`** to prevent shiny patches or missing surfaces in the final visualization.

## Systematic Debugging Workflow

Follow this structured approach to isolate sampling failures:

1. **Enable verbose output** – Set `verbose=True` in the sampler constructor to monitor the progress bar and confirm the full step range executes.
2. **Capture intermediate states** – Extract `pred_x_t` and `pred_x_0` from the result `edict`. Save tensors at intervals (e.g., every 20 steps) to identify when geometry degradation begins.
3. **Visualize progressively** – Use **`render_utils.render_frames`** or **`vis_utils.plot_voxels`** to render intermediate tensors as voxel grids or mesh frames.
4. **Tune hyperparameters** – For under-refined geometry, increase `steps` or lower `sigma_min`. For over-smoothed outputs, decrease `steps` or raise `guidance_strength`.
5. **Validate tensor shapes** – Print the shapes of `cond` and `neg_cond` immediately before calling `sampler.sample()` to catch dimension mismatches.
6. **Inspect raw data** – Visualize a single training sample before sampling to ensure the dataset pipeline produces valid inputs.

## Debug Script for Inspecting Sampling Artifacts

Use this minimal implementation to log intermediate tensors and validate your configuration:

```python
import torch
from trellis2.pipelines.samplers.flow_euler import FlowEulerSampler
from trellis2.pipelines.samplers.classifier_free_guidance_mixin import ClassifierFreeGuidanceSamplerMixin
from trellis2.renderers.mesh_renderer import MeshRenderer
from trellis2.utils.vis_utils import plot_voxels
from trellis2.utils.render_utils import render_frames

# Load model with proper device mapping

model = torch.load("checkpoints/flow_matcher.pt", map_location="cpu")
model.eval()

# Prepare noise tensor: [B, C, D, H, W]

noise = torch.randn(1, 4, 64, 64, 64)
cond = torch.randn(1, 512)  # Example text embedding

neg_cond = torch.zeros_like(cond)

# Instantiate sampler with diagnostic-friendly settings

sampler = FlowEulerSampler(sigma_min=0.01, verbose=True)

# Execute sampling with increased steps for quality

result = sampler.sample(
    model=model,
    x_t=noise,
    cond=cond,
    neg_cond=neg_cond,
    steps=80,
    guidance_strength=0.8,
)

# Debug: Visualize intermediate predictions every 20 steps

for i, (x_t, x_0) in enumerate(zip(result.pred_x_t, result.pred_x_0)):
    if i % 20 == 0:
        plot_voxels(
            x_t.squeeze().cpu().numpy(), 
            title=f"Step {i} (Noisy)"
        )

# Render final geometry

renderer = MeshRenderer()
mesh = renderer.render(result.samples.squeeze())
renderer.show(mesh)  # Launches interactive viewer

```

## Key Source Files for Debugging

These modules contain the critical logic for diagnosing sampling issues:

- **[`trellis2/pipelines/samplers/flow_euler.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/pipelines/samplers/flow_euler.py)** – Implements the `FlowEulerSampler` class with Euler integration and classifier-free guidance mixins.
- **[`trellis2/trainers/flow_matching/flow_matching.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/trainers/flow_matching/flow_matching.py)** – Constructs the flow-matching model and manages checkpoint loading.
- **[`trellis2/pipelines/samplers/base.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/pipelines/samplers/base.py)** – Defines the base `Sampler` interface and common sampling utilities.
- **[`trellis2/renderers/mesh_renderer.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/renderers/mesh_renderer.py)** – Converts raw tensors to renderable meshes with proper normals and UVs.
- **[`trellis2/utils/vis_utils.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/utils/vis_utils.py)** – Provides `plot_voxels` and other visualization helpers for intermediate debugging.
- **[`trellis2/utils/render_utils.py`](https://github.com/microsoft/TRELLIS.2/blob/main/trellis2/utils/render_utils.py)** – Selects appropriate renderers via `get_renderer` and handles frame rendering.
- **`trellis2/datasets/`** – Contains data loaders and preprocessing pipelines that feed conditioned inputs to the sampler.

## Summary

- **Validate configuration**: Keep `sigma_min` between 0 and 1, `steps` above 50 for detail, and guidance parameters within [0, 1].
- **Check conditioning**: Verify `cond` and `neg_cond` tensor shapes match model expectations to prevent silent broadcasting errors.
- **Inspect intermediate states**: Extract `pred_x_t` and `pred_x_0` from the sampler's `edict` output to identify when artifacts first appear.
- **Verify data integrity**: Run [`voxelize_pbr.py`](https://github.com/microsoft/TRELLIS.2/blob/main/voxelize_pbr.py) and visualize inputs with `plot_voxels` to ensure the dataset pipeline produces valid geometry.
- **Recompute normals**: Call `mesh_utils.compute_normals` after sampling to fix rendering artifacts in the final mesh.

## Frequently Asked Questions

### Why is my TRELLIS.2 output empty or containing NaN values?

Empty outputs typically indicate a device mismatch or corrupted checkpoint loading. Use `torch.load(..., map_location='cpu')` when loading models on CPU-only machines, and verify that the checkpoint architecture matches the `FlowEulerSampler` expectations. Check that `sigma_min` is strictly greater than 0 to avoid numerical instability in the noise schedule.

### How do I fix coarse or low-detail geometry in sampled outputs?

Increase the **`steps`** parameter in `FlowEulerSampler.sample()` (e.g., from 50 to 100) to allow more refinement iterations. Additionally, lower **`sigma_min`** to retain more detail in the late stages of denoising. Inspect intermediate `pred_x_0` tensors to confirm detail is present before the final rendering stage.

### What causes color bleeding or semantic mismatches in generated textures?

Color bleeding arises from mismatched dimensions in the conditional inputs. Print the shapes of `cond` and `neg_cond` tensors before sampling—they must match the model's expected embedding dimensions exactly. Ensure your dataset pipeline correctly pre-processes text or image embeddings according to the specifications in **`trellis2/datasets/`**.

### How can I visualize intermediate steps during the sampling process?

The `sample()` method returns an `edict` containing `pred_x_t` (noisy intermediate states) and `pred_x_0` (predicted clean states) for each timestep. Iterate through these lists and pass tensors to **`vis_utils.plot_voxels`** for voxel visualization or **`render_utils.render_frames`** for mesh rendering. This reveals whether artifacts originate during early noise reduction or final denoising.