Stability-AI/generative-models · error · ValueError

provide num_res_blocks either as an int (globally constant)

Error message

provide num_res_blocks either as an int (globally constant) or as a list/tuple (per-level) with the same length as channel_mult

What it means

UNetModel validates that num_res_blocks is either a single int (broadcast to all levels) or a list/tuple whose length equals len(channel_mult). A mismatched list length raises ValueError during model construction.

Source

Thrown at sgm/modules/diffusionmodules/openaimodel.py:606

            ), "Either num_heads or num_head_channels has to be set"

        if num_head_channels == -1:
            assert (
                num_heads != -1
            ), "Either num_heads or num_head_channels has to be set"

        self.in_channels = in_channels
        self.model_channels = model_channels
        self.out_channels = out_channels
        if isinstance(transformer_depth, int):
            transformer_depth = len(channel_mult) * [transformer_depth]
        transformer_depth_middle = transformer_depth[-1]

        if isinstance(num_res_blocks, int):
            self.num_res_blocks = len(channel_mult) * [num_res_blocks]
        else:
            if len(num_res_blocks) != len(channel_mult):
                raise ValueError(
                    "provide num_res_blocks either as an int (globally constant) or "
                    "as a list/tuple (per-level) with the same length as channel_mult"
                )
            self.num_res_blocks = num_res_blocks

        if disable_self_attentions is not None:
            assert len(disable_self_attentions) == len(channel_mult)
        if num_attention_blocks is not None:
            assert len(num_attention_blocks) == len(self.num_res_blocks)
            assert all(
                map(
                    lambda i: self.num_res_blocks[i] >= num_attention_blocks[i],
                    range(len(num_attention_blocks)),
                )
            )
            logpy.info(
                f"Constructor of UNetModel received num_attention_blocks={num_attention_blocks}. "
                f"This option has LESS priority than attention_resolutions {attention_resolutions}, "

View on GitHub (pinned to e8cd657656)

Solutions

  1. Make the num_res_blocks list the same length as channel_mult
  2. Replace the list with a single int to broadcast it to every level
  3. Regenerate the config from the reference model definition

Example fix

// before (yaml)
channel_mult: [1, 2, 4, 4]
num_res_blocks: [2, 2, 2]
// after (yaml)
channel_mult: [1, 2, 4, 4]
num_res_blocks: [2, 2, 2, 2]  # or just 2
Defensive patterns

Strategy: validation

Validate before calling

if not isinstance(num_res_blocks, int) and len(num_res_blocks) != len(channel_mult):
    raise ValueError(
        f"num_res_blocks has length {len(num_res_blocks)} but channel_mult has {len(channel_mult)} levels"
    )

Type guard

def num_res_blocks_ok(nrb, channel_mult) -> bool:
    return isinstance(nrb, int) or (isinstance(nrb, (list, tuple)) and len(nrb) == len(channel_mult))

Try / catch

try:
    model = UNetModel(**unet_config)
except ValueError as e:
    if "num_res_blocks" in str(e):
        unet_config["num_res_blocks"] = unet_config["channel_mult"].__len__() * [2]
        model = UNetModel(**unet_config)
    else:
        raise

Prevention

When it happens

Trigger: Passing num_res_blocks as a list of length != len(channel_mult), e.g. [2,2,2] with channel_mult [1,2,4,4] in the UNet config.

Common situations: Hand-edited diffusion model YAMLs where resolution/channel_mult was changed but num_res_blocks list not updated; porting configs from UNet variants with different level counts.

Related errors


AI-assisted analysis of Stability-AI/generative-models@e8cd657656 (2026-08-29). Data as JSON: /api/errors/70581882b18f3f2c. Report an issue: GitHub.