sgl-project/sglang · error · ValueError

Qwen-Image-Layered requires a non-empty image_path.

Error message

Qwen-Image-Layered requires a non-empty image_path.

What it means

_resolve_layered_image_path normalizes the image_path input for Qwen-Image-Layered: a string is passed through, a non-empty list returns its first element, and everything else (empty list, None, wrong type) raises this error because layered image editing requires at least one reference image.

Source

Thrown at python/sglang/multimodal_gen/runtime/pipelines_core/stages/model_specific_stages/qwen_image_layered.py:64

    return fallback


def _seq_lens_from_optional_mask(
    prompt_embeds: torch.Tensor, prompt_embeds_mask: torch.Tensor | None
) -> list[int]:
    """Return real text lengths, treating a missing mask as all tokens valid."""
    if prompt_embeds_mask is None:
        return [int(prompt_embeds.shape[1])] * int(prompt_embeds.shape[0])
    return [int(x) for x in prompt_embeds_mask.sum(dim=1).tolist()]


def _resolve_layered_image_path(image_path: str | list[str]) -> str:
    if isinstance(image_path, str):
        return image_path
    if isinstance(image_path, list) and image_path:
        return image_path[0]
    raise ValueError("Qwen-Image-Layered requires a non-empty image_path.")


# Copied from diffusers.pipelines.qwenimage.pipeline_qwenimage_edit_plus.calculate_dimensions
def calculate_dimensions(target_area, ratio):
    width = math.sqrt(target_area * ratio)
    height = width / ratio

    width = round(width / 32) * 32
    height = round(height / 32) * 32

    return width, height


# Copied from diffusers.pipelines.stable_diffusion.pipeline_stable_diffusion_img2img.retrieve_latents
def retrieve_latents(
    encoder_output: torch.Tensor,
    generator: Optional[torch.Generator] = None,
    sample_mode: str = "sample",

View on GitHub (pinned to 0132848349)

Solutions

  1. Ensure image_path is a non-empty str or non-empty list[str] before calling forward.
  2. Fix the upstream selection logic that yielded an empty list (check filenames, glob results, dataset fields).
  3. Default to a meaningful fallback image or skip the request when no image is available.

Example fix

# before
stage.forward(image_path=[], ...)

# after
if not image_path:
    raise SkipRequest("no reference image")
stage.forward(image_path=image_path, ...)
Defensive patterns

Strategy: type-guard

Validate before calling

ip = kwargs.get("image_path")
assert isinstance(ip, str) or (isinstance(ip, list) and len(ip) > 0), "image_path required"

Type guard

def valid_image_path(ip) -> bool:
    return isinstance(ip, str) and bool(ip) or isinstance(ip, list) and len(ip) > 0 and all(isinstance(x, str) for x in ip)

Try / catch

try:
    out = stage.forward(...)
except ValueError as e:
    if "non-empty image_path" in str(e):
        skip_or_fallback()
    raise

Prevention

When it happens

Trigger: Calling the layered stage's forward with image_path=[] (empty list), image_path=None, or a non-str/non-list value (e.g. an int or dict).

Common situations: Upstream image download/selection produced zero candidates and the empty list flowed through; conditionally building the image_path list and skipping the append branch; passing a Path object if it isn't coerced to str beforehand (type error path).

Related errors


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