Comfy-Org/ComfyUI · error · ValueError
Input img and txt tensors must have 3 dimensions.
Error message
Input img and txt tensors must have 3 dimensions.
What it means
The main Flux forward() enforces the same token-sequence contract as the controlnet: img and txt must be rank-3 (batch, sequence, channel) tensors. Raw 4D image latents, unbatched 2D tensors, or mis-shaped conditioning raise ValueError before any compute. This mirrors the packed-token format Flux uses end to end.
Source
Thrown at comfy/ldm/flux/model.py:166
self,
img: Tensor,
img_ids: Tensor,
txt: Tensor,
txt_ids: Tensor,
timesteps: Tensor,
y: Tensor,
guidance: Tensor = None,
control = None,
timestep_zero_index=None,
transformer_options={},
attn_mask: Tensor = None,
) -> Tensor:
transformer_options = transformer_options.copy()
patches = transformer_options.get("patches", {})
patches_replace = transformer_options.get("patches_replace", {})
if img.ndim != 3 or txt.ndim != 3:
raise ValueError("Input img and txt tensors must have 3 dimensions.")
# running on sequences img
img = self.img_in(img)
vec = self.time_in(timestep_embedding(timesteps, 256).to(img.dtype))
if self.params.guidance_embed:
if guidance is not None:
vec = vec + self.guidance_in(timestep_embedding(guidance, 256).to(img.dtype))
if self.vector_in is not None:
if y is None:
y = torch.zeros((img.shape[0], self.params.vec_in_dim), device=img.device, dtype=img.dtype)
vec = vec + self.vector_in(y[:, :self.params.vec_in_dim])
if self.txt_norm is not None:
txt = self.txt_norm(txt)
txt = self.txt_in(txt)
if "post_input" in patches:View on GitHub (pinned to 1c6d8d45b3)
Solutions
- Pass Flux sequence latents (B, seq, dim) — in ComfyUI flows these come from the Flux model's own latent packing, not from a VAE decode/encode round trip.
- If writing a custom patch that touches x, return tensors with the same rank you received.
- Add a batch dimension to single samples: txt = txt.unsqueeze(0), img = img.unsqueeze(0).
Example fix
# before noise_pred = model(x_bchw, t, context=txt_2d) # after x_seq = pack(x_bchw) # (B, seq, dim) txt = txt_2d.unsqueeze(0) # (1, seq, dim) noise_pred = model(x_seq, t, context=txt)
Defensive patterns
Strategy: validation
Validate before calling
assert img.ndim == 3 and txt.ndim == 3, f"Flux forward needs (B,seq,dim); img ndim={img.ndim}, txt ndim={txt.ndim}" Type guard
def is_flux_sequence(t: "torch.Tensor") -> bool:
return t.ndim == 3 Prevention
- Route calls through ComfyUI's model patcher/sampler so latent packing is handled for you.
- In custom transformer patches, preserve tensor rank on return.
- unsqueeze(0) single-image batches before forward.
When it happens
Trigger: Calling model.forward() (or a sampler invoking it) with img of shape (B,C,H,W) instead of packed (B,seq,dim); txt embeddings of rank 2 (missing batch dim); tensors flattened incorrectly by a custom patch or wrapper.
Common situations: Custom sampling loops that bypass ComfyUI's model patcher and pass VAE latents directly; transformer patches (patches_replace) that reshape x and return the wrong rank; debugging code that feeds a single image without a batch dim.
Related errors
- Input img and txt tensors must have 3 dimensions.
- Input img and txt tensors must have 3 dimensions.
- Input img tensor must be in [B, C, H, W] format.
- Input txt tensors must have 3 dimensions.
- HiDreamO1Transformer requires input_ids and position_ids in
AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14).
Data as JSON: /api/errors/a158751312533430.
Report an issue: GitHub.