lllyasviel/Fooocus · error · ValueError

scale {scale} is not supported. Supported scales: 2^n and 3.

Error message

scale {scale} is not supported. Supported scales: 2^n and 3.

What it means

HAT.Upsample has the same tail logic as the other BasicSR-derived transformers: power-of-two scales via repeated 2x PixelShuffle, one 3x branch, everything else rejected. The HAT (Hybrid Attention Transformer) architecture cannot be built for any other upscale factor.

Source

Thrown at ldm_patched/pfn/architecture/HAT.py:841

class Upsample(nn.Sequential):
    """Upsample module.
    Args:
        scale (int): Scale factor. Supported scales: 2^n and 3.
        num_feat (int): Channel number of intermediate features.
    """

    def __init__(self, scale, num_feat):
        m = []
        if (scale & (scale - 1)) == 0:  # scale = 2^n
            for _ in range(int(math.log(scale, 2))):
                m.append(nn.Conv2d(num_feat, 4 * num_feat, 3, 1, 1))
                m.append(nn.PixelShuffle(2))
        elif scale == 3:
            m.append(nn.Conv2d(num_feat, 9 * num_feat, 3, 1, 1))
            m.append(nn.PixelShuffle(3))
        else:
            raise ValueError(
                f"scale {scale} is not supported. " "Supported scales: 2^n and 3."
            )
        super(Upsample, self).__init__(*m)


class HAT(nn.Module):
    r"""Hybrid Attention Transformer
        A PyTorch implementation of : `Activating More Pixels in Image Super-Resolution Transformer`.
        Some codes are based on SwinIR.
    Args:
        img_size (int | tuple(int)): Input image size. Default 64
        patch_size (int | tuple(int)): Patch size. Default: 1
        in_chans (int): Number of input image channels. Default: 3
        embed_dim (int): Patch embedding dimension. Default: 96
        depths (tuple(int)): Depth of each Swin Transformer layer.
        num_heads (tuple(int)): Number of attention heads in different layers.
        window_size (int): Window size. Default: 7
        mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. Default: 4

View on GitHub (pinned to ae05379cc9)

Solutions

  1. Use upscale=2, 4, 8 or 3 for HAT
  2. Chain a 2x and a 3x HAT pass for 6x output
  3. Add an upfront assert on the config value so the failure is caught at config-load time, not model build time

Example fix

# before
m = HAT(upscale=5, ...)  # -> ValueError: scale 5 is not supported

# after
assert upscale == 3 or (upscale & (upscale - 1)) == 0, 'HAT needs scale 2^n or 3'
m = HAT(upscale=4, ...)
Defensive patterns

Strategy: validation

Validate before calling

def valid_sr_scale(scale) -> bool:
    return scale == 3 or (isinstance(scale, int) and scale > 1 and (scale & (scale - 1)) == 0)

upscale = cfg.get('upscale', 4)
if not valid_sr_scale(upscale):
    cfg['upscale'] = 4  # or reject the config

Type guard

def is_supported_hat_scale(scale) -> bool:
    return isinstance(scale, int) and (scale == 3 or (scale & (scale - 1)) == 0)

Prevention

When it happens

Trigger: Constructing HAT with upscale outside {2,4,8,...,3}, e.g. 5 or 7; most often the 'upscale' value comes from an upscaler registration dict or model YAML and is not sanity-checked before __init__.

Common situations: Custom upscaler YAMLs copied between architectures; computed scales like upscale = target_size // input_size landing on 6; scripts registering HAT for arbitrary x-values.

Related errors


AI-assisted analysis of lllyasviel/Fooocus@ae05379cc9 (2026-08-15). Data as JSON: /api/errors/a38877df1197b641. Report an issue: GitHub.