Comfy-Org/ComfyUI · error · ValueError

The provided model does not have a heatmap_head. Please use

Error message

The provided model does not have a heatmap_head. Please use SDPose model from here https://huggingface.co/Comfy-Org/SDPose/tree/main/checkpoints.

What it means

Raised by the SDPose node when the loaded diffusion model's diffusion_model lacks a heatmap_head attribute. SDPose checkpoints ship with an extra heatmap head attached to the DiT; a plain checkpoint of the same family will not have it, and the node cannot extract the 640-channel features it needs via the output_block_patch hook.

Source

Thrown at comfy_extras/nodes_sdpose.py:477

    @classmethod
    def execute(cls, model, vae, image, batch_size, bboxes=None) -> io.NodeOutput:

        height, width = image.shape[-3], image.shape[-2]
        context = LotusConditioning().execute().result[0]

        # Use output_block_patch to capture the last 640-channel feature
        def output_patch(h, hsp, transformer_options):
            nonlocal captured_feat
            if h.shape[1] == 640:  # Capture the features for wholebody
                captured_feat = h.clone()
            return h, hsp

        model_clone = model.clone()
        model_clone.model_options["transformer_options"] = {"patches": {"output_block_patch": [output_patch]}}

        if not hasattr(model.model.diffusion_model, 'heatmap_head'):
            raise ValueError("The provided model does not have a heatmap_head. Please use SDPose model from here https://huggingface.co/Comfy-Org/SDPose/tree/main/checkpoints.")

        head = model.model.diffusion_model.heatmap_head
        total_images = image.shape[0]
        captured_feat = None

        model_w = int(head.heatmap_size[0]) * 4   # 192 * 4 = 768
        model_h = int(head.heatmap_size[1]) * 4   # 256 * 4 = 1024

        def _resize_to_model(imgs):
            """Stretch BHWC images to (model_h, model_w), model expects no aspect preservation."""
            h, w = imgs.shape[-3], imgs.shape[-2]
            method = "area" if (model_h <= h and model_w <= w) else "bilinear"
            chw = imgs.permute(0, 3, 1, 2).float()
            scaled = comfy.utils.common_upscale(chw, model_w, model_h, upscale_method=method, crop="disabled")
            return scaled.permute(0, 2, 3, 1), model_w / w, model_h / h

        def _remap_keypoints(kp, scale_x, scale_y, offset_x=0, offset_y=0):
            """Remap keypoints from model space back to original image space."""

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Download and load the official SDPose checkpoint from https://huggingface.co/Comfy-Org/SDPose/tree/main/checkpoints.
  2. Verify the checkpoint actually contains heatmap_head weights (inspect state dict keys before loading).
  3. If converting/quantizing SDPose yourself, keep the heatmap_head module and its keys intact.
Defensive patterns

Strategy: validation

Validate before calling

# Before running, confirm the loaded model carries the SDPose head
if not hasattr(model.model.diffusion_model, 'heatmap_head'):
    raise ValueError("loaded checkpoint is not SDPose; use Comfy-Org/SDPose checkpoints")

Type guard

def is_sdpose_model(model) -> bool:
    dm = getattr(getattr(model, 'model', None), 'diffusion_model', None)
    return dm is not None and hasattr(dm, 'heatmap_head')

Prevention

When it happens

Trigger: Loading a non-SDPose checkpoint (or a base model without the auxiliary head) into the SDPose node; a custom/fine-tuned variant where heatmap_head was stripped; converting a checkpoint with a script that drops non-standard keys.

Common situations: Pointing the loader at the wrong local checkpoint; using a quantized/reforged SDPose whose converter dropped the head; assuming any Flux-architecture model works because input shapes match.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/c4d220c6f40d8493. Report an issue: GitHub.