sgl-project/sglang · error · ValueError

Unrecognized image input, support local path, http url, base

Error message

Unrecognized image input, support local path, http url, base64 and PIL.Image, got {image}

What it means

Raised by fetch_image when the image argument can't be opened through any supported route (local path via Image.open, bytes via BytesIO, base64, or PIL.Image) and image_obj ends up None. The message echoes the offending input value.

Source

Thrown at python/sglang/srt/multimodal/processors/mimo_v2.py:1468

            image_obj = image
        elif isinstance(image, str):
            if image.startswith("http://") or image.startswith("https://"):
                with BytesIO(download_remote_media(image, timeout=3)) as bio:
                    image_obj = copy.deepcopy(Image.open(bio))
            elif image.startswith("file://"):
                image_obj = Image.open(image[7:])
            elif image.startswith("data:image"):
                if "base64," in image:
                    _, base64_data = image.split("base64,", 1)
                    data = base64.b64decode(base64_data)
                    with BytesIO(data) as bio:
                        image_obj = copy.deepcopy(Image.open(bio))
            else:
                image_obj = Image.open(image)
        else:
            image_obj = Image.open(BytesIO(image))
        if image_obj is None:
            raise ValueError(
                f"Unrecognized image input, support local path, http url, base64 and PIL.Image, got {image}"
            )
        image = cls.to_rgb(image_obj)
        return image


class MiMoV2Processor(BaseMultimodalProcessor):
    models = [MiMoV2ForCausalLM]

    @staticmethod
    def _normalize_config_dict(config, name: str) -> dict:
        if config is None:
            return {}
        if isinstance(config, dict):
            return config
        if hasattr(config, "to_dict"):
            return config.to_dict()
        raise ValueError(f"{name} must be a dict-like config, got {type(config)}")

View on GitHub (pinned to 0132848349)

Solutions

  1. Send a plain base64 string (strip 'data:image/...;base64,' prefixes) or raw image bytes
  2. Verify the image opens locally: PIL.Image.open(BytesIO(b64decode(s))).verify()
  3. For local files, pass the filesystem path string

Example fix

# before
img_b64 = 'data:image/png;base64,iVBOR...'   # prefix not stripped
# after
import base64
img_b64 = 'iVBOR...'  # or base64.b64encode(open('x.png','rb').read()).decode()
Defensive patterns

Strategy: validation

Validate before calling

from io import BytesIO
from PIL import Image
import base64, re
def is_loadable_image(s):
    try:
        raw = base64.b64decode(re.sub(r'^data:[^;]+;base64,', '', s))
        Image.open(BytesIO(raw)).verify()
        return True
    except Exception:
        return False

Type guard

def is_recognized_image_input(x) -> bool:
    return (isinstance(x, (str, bytes)) or isinstance(x, Image.Image)) and \
           (not isinstance(x, str) or not x.startswith('data:'))

Try / catch

try:
    im = MiMoProcessor.fetch_image(image)
except ValueError as e:
    if 'Unrecognized image input' in str(e):
        return error_response(400, 'send base64 without data-URI prefix, raw bytes, a path, or a URL')
    raise

Prevention

When it happens

Trigger: Calling process_image/fetch_image with a value that falls through all branches — e.g. a malformed base64 string that decodes to nothing openable, a file-like object, an int/None, or a corrupt byte payload that Image.open silently fails on in this flow.

Common situations: Bad base64 (missing padding, data-URI prefix not stripped); corrupt image bytes; clients sending file handles instead of bytes; None values slipping through request parsing.

Related errors


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