Comfy-Org/ComfyUI · 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
Raised by UNetModel (openaimodel.py) when num_res_blocks is given as a list/tuple whose length differs from channel_mult. The constructor accepts either one int (applied to all levels) or a per-level sequence that must align 1:1 with channel_mult; a mismatch means the config is ambiguous and construction aborts.
Source
Thrown at comfy/ldm/modules/diffusionmodules/openaimodel.py:476
if num_heads_upsample == -1:
num_heads_upsample = num_heads
if num_heads == -1:
assert num_head_channels != -1, '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(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:
# should be a list of booleans, indicating whether to disable self-attention in TransformerBlocks or not
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)
transformer_depth = transformer_depth[:]
transformer_depth_output = transformer_depth_output[:]
self.dropout = dropout
self.channel_mult = channel_mult
self.conv_resample = conv_resample
self.num_classes = num_classes
self.use_checkpoint = use_checkpoint
self.dtype = dtypeView on GitHub (pinned to 1c6d8d45b3)
Solutions
- Make len(num_res_blocks) == len(channel_mult), or pass a single int
- Diff the config against the original checkpoint's config to find which level list drifted
- If you added a channel_mult level, add the matching num_res_blocks entry
Example fix
# before UNetModel(channel_mult=(1, 2, 4, 8), num_res_blocks=[2, 2, 2]) # after UNetModel(channel_mult=(1, 2, 4, 8), num_res_blocks=[2, 2, 2, 2])
Defensive patterns
Strategy: validation
Validate before calling
if isinstance(num_res_blocks, (list, tuple)) and len(num_res_blocks) != len(channel_mult):
raise ValueError(f'num_res_blocks len {len(num_res_blocks)} != channel_mult len {len(channel_mult)}')
model = UNetModel(num_res_blocks=num_res_blocks, channel_mult=channel_mult) Type guard
def num_res_blocks_valid(nrb, channel_mult) -> bool:
return isinstance(nrb, int) or len(nrb) == len(channel_mult) Prevention
- Validate per-level config lists (num_res_blocks, channel_mult, attentions) for equal length before constructing UNets
- When editing configs, change levels in all aligned lists together
When it happens
Trigger: Passing num_res_blocks=[2,2,2,2] with channel_mult=[1,2,4,6] (length 4 vs 3), or a truncated/extended per-level list from an edited config.
Common situations: Hand-tuning SD-style UNet configs for depth; porting configs between model variants (base vs depth variants list different channel_mult lengths); diffusers-to-ComfyUI config conversions dropping or adding a level.
Related errors
- unsupported dimensions: {dims}
- INVALID_TAG_FILTER
- Control type {max_type_name}({max_type}) is out of range for
- Block type {block_type} not supported
- Unknown pos_emb_cls {self.pos_emb_cls}
AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14).
Data as JSON: /api/errors/8a47938c1e3471f9.
Report an issue: GitHub.