invoke-ai/InvokeAI · error · ValueError
Unexpected dtype '{dtype}'.
Error message
Unexpected dtype '{dtype}'. What it means
supports_dtype checks whether the loaded spandrel model supports half, bfloat16, or float32 precision by delegating to the underlying descriptor's supports_* flags. Any dtype outside torch.float16, torch.bfloat16, torch.float32 (e.g. float64, int types) has no mapping and raises ValueError.
Source
Thrown at invokeai/backend/spandrel_image_to_image_model.py:99
if not isinstance(model, ImageModelDescriptor):
raise ValueError(
f"Loaded a spandrel model of type '{type(model)}'. Only image-to-image models are supported "
"('ImageModelDescriptor')."
)
return cls(spandrel_model=model)
def supports_dtype(self, dtype: torch.dtype) -> bool:
"""Check if the model supports the given dtype."""
if dtype == torch.float16:
return self._spandrel_model.supports_half
elif dtype == torch.bfloat16:
return self._spandrel_model.supports_bfloat16
elif dtype == torch.float32:
# All models support float32.
return True
else:
raise ValueError(f"Unexpected dtype '{dtype}'.")
def get_model_type_name(self) -> str:
"""The model type name. Intended for logging / debugging purposes. Do not rely on this field remaining
consistent over time.
"""
return str(type(self._spandrel_model.model))
def to(
self,
device: Optional[torch.device] = None,
dtype: Optional[torch.dtype] = None,
non_blocking: bool = False,
) -> None:
"""Note: Some models have limited dtype support. Call supports_dtype(...) to check if the dtype is supported.
Note: The non_blocking parameter is currently ignored."""
# TODO(ryand): spandrel.ImageModelDescriptor.to(...) does not support non_blocking. We will have to access the
# model directly if we want to apply this optimization.
self._spandrel_model.to(device=device, dtype=dtype)View on GitHub (pinned to 0b6a024f2f)
Solutions
- Only pass torch.float16, torch.bfloat16, or torch.float32 to supports_dtype.
- Convert the requested dtype first (e.g. dtype = torch.float16 if dtype not in allowed set).
- Check upstream code that derives dtype so it can't produce exotic values.
- Catch ValueError and fall back to torch.float32, which all models support.
Example fix
// before
model.supports_dtype(torch.float64)
// after
allowed = {torch.float16, torch.bfloat16, torch.float32}
dtype = dtype if dtype in allowed else torch.float32
model.supports_dtype(dtype) Defensive patterns
Strategy: validation
Validate before calling
SUPPORTED = {torch.float16, torch.bfloat16, torch.float32}
if dtype not in SUPPORTED:
dtype = torch.float32 Type guard
def is_supported_dtype(dtype) -> bool:
return dtype in {torch.float16, torch.bfloat16, torch.float32} Try / catch
try:
ok = model.supports_dtype(dtype)
except ValueError:
ok = model.supports_dtype(torch.float32) # universal fallback Prevention
- Always derive dtype from the allowed set {fp16, bf16, fp32}
- Never pass string dtypes; convert with getattr(torch, s) and validate
- Default to float32 when unsure
- Log the resolved dtype before loading
When it happens
Trigger: Calling supports_dtype(dtype) with a dtype other than torch.float16/bfloat16/float32, typically from _load_model when converting the model to an unexpected precision.
Common situations: Passing dtype strings ('fp16') instead of torch dtype objects; config or variant plumbing delivering torch.float64 or a quantized dtype; custom code selecting dtype = latents.dtype when latents are not a float16/32 type.
Related errors
- Invalid mode selected
- Unexpected control_input type: ${type(control_input)}
- Unexpected T2I-Adapter base model type: '${t2i_adapter_model
- 'latents' or 'noise' must be provided!
- Incompatible 'noise' and 'latents' shapes: ${latents.shape=}
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/90d7d354987e26e4.
Report an issue: GitHub.