sgl-project/sglang · error · ValueError

input image is empty

Error message

input image is empty

What it means

Raised by recenter in mesh3d_utils.py when the nonzero bounding box of a mask collapses to zero height or width (crop_h == 0 or crop_w == 0). Because coords = np.nonzero(mask) on a fully-empty mask yields min/max over empty arrays producing a degenerate box, the function cannot build a centered crop.

Source

Thrown at python/sglang/multimodal_gen/runtime/utils/mesh3d_utils.py:978

        if image.shape[-1] == 4:
            mask = image[..., 3]
        else:
            mask = np.ones_like(image[..., 0:1]) * 255
            image = np.concatenate([image, mask], axis=-1)
            mask = mask[..., 0]

        height, width, channels = image.shape

        size = max(height, width)
        result = np.zeros((size, size, channels), dtype=np.uint8)

        coords = np.nonzero(mask)
        x_min, x_max = coords[0].min(), coords[0].max()
        y_min, y_max = coords[1].min(), coords[1].max()
        crop_h = x_max - x_min
        crop_w = y_max - y_min
        if crop_h == 0 or crop_w == 0:
            raise ValueError("input image is empty")
        desired_size = int(size * (1 - border_ratio))
        scale = desired_size / max(crop_h, crop_w)
        scaled_h = int(crop_h * scale)
        scaled_w = int(crop_w * scale)
        x2_min = (size - scaled_h) // 2
        x2_max = x2_min + scaled_h

        y2_min = (size - scaled_w) // 2
        y2_max = y2_min + scaled_w

        result[x2_min:x2_max, y2_min:y2_max] = cv2.resize(
            image[x_min:x_max, y_min:y_max],
            (scaled_w, scaled_h),
            interpolation=cv2.INTER_AREA,
        )

        bg = np.ones((result.shape[0], result.shape[1], 3), dtype=np.uint8) * 255

View on GitHub (pinned to 0132848349)

Solutions

  1. Check mask.any() / mask.sum() > 0 before calling recenter
  2. Verify the mask isn't inverted or thresholded too hard — inspect unique values np.unique(mask)
  3. Confirm you're passing the correct mask array (right channel, right dtype, 0/255 vs 0/1 range)
  4. Re-run or swap the upstream segmentation/matting model if it produces empty masks

Example fix

// before
recenter(image, mask, size=512)

// after
if not mask.any():
    raise ValueError("empty mask; skipping recenter")
recenter(image, mask, size=512)
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def mask_is_usable(mask: np.ndarray) -> bool:
    m = np.asarray(mask)
    nz = np.nonzero(m)
    return nz[0].size > 1 and nz[1].size > 1  # non-degenerate bbox

if not mask_is_usable(mask):
    raise ValueError("mask empty or degenerate; skip recenter")

Try / catch

try:
    recenter(image, mask, size=size)
except ValueError as e:
    if "input image is empty" in str(e):
        # fall back to plain resize without cropping
        pass

Prevention

When it happens

Trigger: Calling load_image / recenter with an all-zero mask; masks where nonzero pixels form a single row or column after thresholding also trigger it (crop_h or crop_w becomes 0).

Common situations: Thresholding masks too aggressively (everything below threshold); matting/segmentation models returning empty masks for images with no detected subject; wrong mask channel or inverted mask passed in; grayscale images converted incorrectly so the mask is all background.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/cccd9504aefe31b4. Report an issue: GitHub.