sgl-project/sglang · error · TypeError
Expected a PIL image, got {type(image)}
Error message
Expected a PIL image, got {type(image)} What it means
The Dots3 image processor only accepts PIL Image objects; anything else (numpy array, tensor, file path, bytes, base64 string) fails this isinstance check immediately. This mirrors Qwen-VL-style processors that operate on PIL's mode/size API (e.g. RGBA compositing, convert('RGB')).
Source
Thrown at python/sglang/srt/models/dots3_common/dots_omni_towers.py:151
resized_h = max(factor, self._round_by_factor(height, factor))
resized_w = max(factor, self._round_by_factor(width, factor))
if resized_h * resized_w > max_pixels:
beta = math.sqrt(height * width / max_pixels)
resized_h = max(factor, self._floor_by_factor(height / beta, factor))
resized_w = max(factor, self._floor_by_factor(width / beta, factor))
elif resized_h * resized_w < min_pixels:
beta = math.sqrt(min_pixels / (height * width))
resized_h = self._ceil_by_factor(height * beta, factor)
resized_w = self._ceil_by_factor(width * beta, factor)
if resized_h * resized_w > max_pixels:
beta = math.sqrt(resized_h * resized_w / max_pixels)
resized_h = max(factor, self._floor_by_factor(resized_h / beta, factor))
resized_w = max(factor, self._floor_by_factor(resized_w / beta, factor))
return resized_h, resized_w
def _process_image(self, image, detail="auto"):
if not isinstance(image, Image.Image):
raise TypeError(f"Expected a PIL image, got {type(image)}")
if image.mode == "RGBA":
background = Image.new("RGB", image.size, (255, 255, 255))
background.paste(image, mask=image.getchannel("A"))
image = background
elif image.mode != "RGB":
image = image.convert("RGB")
detail_config = self.image_detail_config.get(detail, {})
resized_h, resized_w = self._resized_size(
*image.size,
min_pixels=detail_config.get("min_pixels", self.min_pixels),
max_pixels=detail_config.get("max_pixels", self.max_pixels),
target_height=detail_config.get("target_height"),
target_width=detail_config.get("target_width"),
)
image = image.resize((resized_w, resized_h), Image.Resampling.BICUBIC)
array = np.asarray(image, dtype=np.float32) / 255.0
array = (array - self.image_mean) / self.image_stdView on GitHub (pinned to 0132848349)
Solutions
- Convert the input to PIL before calling: Image.fromarray(arr) (and cv2.cvtColor BGR->RGB if from OpenCV)
- For file paths, open with Image.open(path) and pass the result
- For raw bytes, wrap in io.BytesIO and Image.open
- Standardize the multimodal request pipeline to always deliver PIL RGB images
Example fix
# before
arr = cv2.imread('x.jpg')
processor.process_images([arr])
# after
from PIL import Image
img = Image.fromarray(cv2.cvtColor(arr, cv2.COLOR_BGR2RGB))
processor.process_images([img]) Defensive patterns
Strategy: type-guard
Validate before calling
from PIL import Image
def to_pil(x):
if isinstance(x, Image.Image):
return x
import numpy as np, io
if isinstance(x, bytes):
return Image.open(io.BytesIO(x))
if isinstance(x, str):
return Image.open(x)
if isinstance(x, np.ndarray):
return Image.fromarray(x)
raise TypeError(f'cannot convert {type(x)} to PIL') Type guard
def is_pil_image(x) -> bool:
from PIL import Image
return isinstance(x, Image.Image) Try / catch
try:
processor.process_images([img])
except TypeError as e:
if 'PIL image' in str(e):
img = to_pil(raw)
else:
raise Prevention
- Convert cv2 arrays with BGR->RGB + Image.fromarray
- Wrap request handlers to normalize inputs to PIL
- Open paths with Image.open before passing
When it happens
Trigger: Calling process_images with a numpy ndarray, torch.Tensor, raw bytes, or a file path instead of a PIL.Image.Image instance. Internally the code needs image.mode and Image.new/paste, so non-PIL input is rejected up front.
Common situations: Loading images with cv2.imread (returns BGR ndarray), passing decoded byte buffers from an HTTP handler, or handing over a path string assuming the library will open it.
Related errors
- Unsupported image type: {type(image)}
- Unsupported video input type for EPD encoder: {type(video_da
- unsupported audio item: loaded={loaded_type}, raw={raw_type}
- When using multiple prompts with multiple input images, prov
- {key}.position_ids is required
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/6f4f03f480197de9.
Report an issue: GitHub.