invoke-ai/InvokeAI · error · ValueError
Unexpected submodel requested for Spandrel model.
Error message
Unexpected submodel requested for Spandrel model.
What it means
Spandrel image-to-image models are single-file upscalers/restoration networks with no submodels. The loader raises this ValueError if any submodel_type is supplied. It is a contract guard, similar to the SigLIP and TI loaders.
Source
Thrown at invokeai/backend/model_manager/load/model_loaders/spandrel_image_to_image.py:25
from invokeai.backend.model_manager.load.load_default import ModelLoader
from invokeai.backend.model_manager.load.model_loader_registry import ModelLoaderRegistry
from invokeai.backend.model_manager.taxonomy import AnyModel, BaseModelType, ModelFormat, ModelType, SubModelType
from invokeai.backend.spandrel_image_to_image_model import SpandrelImageToImageModel
@ModelLoaderRegistry.register(
base=BaseModelType.Any, type=ModelType.SpandrelImageToImage, format=ModelFormat.Checkpoint
)
class SpandrelImageToImageModelLoader(ModelLoader):
"""Class for loading Spandrel Image-to-Image models (i.e. models wrapped by spandrel.ImageModelDescriptor)."""
def _load_model(
self,
config: AnyModelConfig,
submodel_type: Optional[SubModelType] = None,
) -> AnyModel:
if submodel_type is not None:
raise ValueError("Unexpected submodel requested for Spandrel model.")
model_path = Path(config.path)
model = SpandrelImageToImageModel.load_from_file(model_path)
torch_dtype = self._torch_dtype
if not model.supports_dtype(torch_dtype):
self._logger.warning(
f"The configured dtype ('{self._torch_dtype}') is not supported by the {model.get_model_type_name()} "
"model. Falling back to 'float32'."
)
torch_dtype = torch.float32
model.to(dtype=torch_dtype)
return model
View on GitHub (pinned to 0b6a024f2f)
Solutions
- Pass submodel_type=None when loading Spandrel models.
- Route diffusion-submodel requests to the appropriate main-model loader instead.
- Guard the call site by checking the model type before supplying a submodel_type.
Example fix
// before model = loader.load_model(config, submodel_type=SubModelType.VAE) // after model = loader.load_model(config, submodel_type=None)
Defensive patterns
Strategy: validation
Validate before calling
if model_type is ModelType.Spandrel and submodel_type is not None:
submodel_type = None # Spandrel models are loaded whole Type guard
def is_whole_model_type(model_type: ModelType) -> bool:
return model_type in {ModelType.Spandrel, ModelType.SigLIP, ModelType.TextualInversion, ModelType.TextLLM} Try / catch
try:
model = loader.load_model(config, submodel_type=None)
except ValueError as e:
logger.error("Spandrel load failed: %s", e)
raise Prevention
- Never attach submodel requests to upscaler/restoration models.
- Normalize submodel_type to None in dispatchers for non-pipeline model types.
- Add unit tests covering loader dispatch per model type.
When it happens
Trigger: Calling load_model on a Spandrel model config with submodel_type set (e.g. SubModelType.Transformer or VAE) instead of None.
Common situations: Generic loading code that always passes a submodel_type because it was written for main diffusion pipelines; misconfigured pipeline code routing an upscale request through submodel logic.
Related errors
- Admin privileges required
- There are no submodels in a LoRA model.
- Unexpected submodel requested for LLaVA OneVision model.
- Unexpected submodel requested for TextLLM model.
- There are no submodels in a TI model.
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/40f1b4e085436582.
Report an issue: GitHub.