Comfy-Org/ComfyUI · error · ValueError

The connected model_patch is not an LTX duration head.

Error message

The connected model_patch is not an LTX duration head.

What it means

Raised by the LTX duration-prediction node's execute(): it takes the model_patch-style input 'duration_head' and checks isinstance(head, comfy.ldm.lightricks.duration_head.DurationHead). Any other model-patch object (ControlNet, LoRA hook, IP-Adapter patch, plain ModelPatch) fails the check because the node needs the DurationHead module to run the caption connectors exactly as sampling does.

Source

Thrown at comfy_extras/nodes_lt.py:1153

                io.Conditioning.Input("positive"),
                io.Custom("MODEL_PATCH").Input("duration_head",
                                               tooltip="LTX 2.4 duration head loaded with ModelPatchLoader."),
                io.Float.Input("frame_rate", default=24.0, min=1.0, max=120.0, step=0.01),
                io.Float.Input("min_seconds", default=1.0, min=0.5, max=120.0, step=0.1),
                io.Float.Input("max_seconds", default=20.0, min=0.5, max=120.0, step=0.1),
            ],
            outputs=[
                io.Int.Output(display_name="num_frames"),
                io.Float.Output(display_name="seconds", tooltip="Raw (unclamped) predicted duration."),
            ],
        )

    @classmethod
    def execute(cls, model, positive, duration_head, frame_rate, min_seconds, max_seconds) -> io.NodeOutput:
        dm = model.model.diffusion_model
        head = duration_head.model
        if not isinstance(head, comfy.ldm.lightricks.duration_head.DurationHead):
            raise ValueError("The connected model_patch is not an LTX duration head.")

        context = positive[0][0]
        meta = positive[0][1]
        if context.shape[0] != 1:
            context = context[:1]

        # Run the caption connectors exactly the way sampling does.
        comfy.model_management.load_models_gpu([model, duration_head])
        device = model.load_device
        head = head.to(device)
        with torch.no_grad():
            context = context.to(device=device, dtype=model.model.get_dtype_inference())
            processed = dm.preprocess_text_embeds(context, unprocessed=meta.get("unprocessed_ltxav_embeds", False))
            video_tokens = processed[..., :dm.cross_attention_dim].float()
            audio_tokens = processed[..., dm.cross_attention_dim:].float()
            seconds = float(head(video_tokens, audio_tokens)[0])

        num_frames = comfy.ldm.lightricks.duration_head.seconds_to_num_frames(

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Connect the output of the dedicated LTX duration-head loader node (the one that yields a DurationHead-backed model patch) into duration_head.
  2. Remove any intermediate patch-application nodes between the loader and this input.
  3. Verify visually that duration_head is not fed by a ControlNet/LoRA loader.
Defensive patterns

Strategy: type-guard

Validate before calling

import comfy.ldm.lightricks.duration_head as dh
assert isinstance(duration_head.model, dh.DurationHead), (
    "duration_head input must come from the LTX duration-head loader, not a generic model patch")

Type guard

def is_ltx_duration_head(model_patch) -> bool:
    import comfy.ldm.lightricks.duration_head as dh
    return isinstance(getattr(model_patch, "model", None), dh.DurationHead)

Prevention

When it happens

Trigger: Connecting the output of a generic LoadPatch or a ControlNet/LoRA loader into the duration_head input; connecting a ModelPatchDXL-style wrapper whose .model is not a DurationHead; forgetting the dedicated LTX duration-head loader node.

Common situations: Building the LTX-2 duration workflow and grabbing the wrong loader node from the menu; reusing a template where the patch slot was rewired.

Related errors


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