Comfy-Org/ComfyUI · error · ValueError

Passing a list or tuple of seeds to BatchedBrownianTree requ

Error message

Passing a list or tuple of seeds to BatchedBrownianTree requires a length matching the batch size.

What it means

Raised by BatchedBrownianTree.__init__ when seed is a list/tuple whose length differs from x.shape[0]. When per-sample seeds are supplied, the sampler builds one torchsde.BrownianTree per seed, so the seed sequence must cover the whole batch dimension exactly.

Source

Thrown at comfy/k_diffusion/sampling.py:105

    return lambda sigma, sigma_next: torch.randn(x.size(), dtype=x.dtype, layout=x.layout, device=x.device, generator=generator)


class BatchedBrownianTree:
    """A wrapper around torchsde.BrownianTree that enables batches of entropy."""

    def __init__(self, x, t0, t1, seed=None, **kwargs):
        self.cpu_tree = kwargs.pop("cpu", True)
        t0, t1, self.sign = self.sort(t0, t1)
        w0 = kwargs.pop('w0', None)
        if w0 is None:
            w0 = torch.zeros_like(x)
        self.batched = False
        if seed is None:
            seed = (torch.randint(0, 2 ** 63 - 1, ()).item(),)
        elif isinstance(seed, (tuple, list)):
            if len(seed) != x.shape[0]:
                raise ValueError("Passing a list or tuple of seeds to BatchedBrownianTree requires a length matching the batch size.")
            self.batched = True
            w0 = w0[0]
        else:
            seed = (seed,)
        if self.cpu_tree:
            t0, w0, t1 = t0.detach().cpu(), w0.detach().cpu(), t1.detach().cpu()
        self.trees = tuple(torchsde.BrownianTree(t0, w0, t1, entropy=s, **kwargs) for s in seed)

    @staticmethod
    def sort(a, b):
        return (a, b, 1) if a < b else (b, a, -1)

    def __call__(self, t0, t1):
        t0, t1, sign = self.sort(t0, t1)
        device, dtype = t0.device, t0.dtype
        if self.cpu_tree:
            t0, t1 = t0.detach().cpu().float(), t1.detach().cpu().float()
        w = torch.stack([tree(t0, t1) for tree in self.trees]).to(device=device, dtype=dtype) * (self.sign * sign)

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Make len(seed) == x.shape[0]: generate exactly batch_size seeds
  2. Or pass a single int seed, which torch.randint-expands internally to the whole batch
  3. Recompute the seed list whenever batch size changes rather than caching it

Example fix

# before
noise_sampler = BrownianTreeNoiseSampler(x, sigma_min, sigma_max, seed=[123, 456])  # x.shape[0] == 4
# after
noise_sampler = BrownianTreeNoiseSampler(x, sigma_min, sigma_max, seed=[123, 456, 789, 1011])
Defensive patterns

Strategy: validation

Validate before calling

if isinstance(seeds, (list, tuple)):
    assert len(seeds) == x.shape[0], f'need {x.shape[0]} seeds, got {len(seeds)}'
noise_sampler = BrownianTreeNoiseSampler(x, sigma_min, sigma_max, seed=seeds)

Type guard

def seeds_match_batch(seeds, x: torch.Tensor) -> bool:
    return not isinstance(seeds, (list, tuple)) or len(seeds) == x.shape[0]

Prevention

When it happens

Trigger: Constructing BrownianTreeNoiseSampler(x, ..., seed=[s1, s2]) for a latent batch of size != 2, or a custom sampler passing extra_args['seed'] as a list that was built for a different batch size than the current latent.

Common situations: Workflows that vary batch_size dynamically (batch size widget changed after a per-seed list was computed); API scripts generating seed lists from a stale shape; custom nodes forwarding user seed lists without resizing to the actual batch.

Related errors


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