invoke-ai/InvokeAI · 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
Flux.forward expects the image latent tensor (img) and text embedding tensor (txt) to be rank-3: (batch, seq_len, channels). If either has another rank (e.g. 4D image latents straight from the VAE, or 2D unbatched tensors), the sequence-linear projections downstream would be wrong, so forward raises immediately.
Source
Thrown at invokeai/backend/flux/model.py:107
def forward(
self,
img: Tensor,
img_ids: Tensor,
txt: Tensor,
txt_ids: Tensor,
timesteps: Tensor,
y: Tensor,
guidance: Tensor | None,
timestep_index: int,
total_num_timesteps: int,
controlnet_double_block_residuals: list[Tensor] | None,
controlnet_single_block_residuals: list[Tensor] | None,
ip_adapter_extensions: list[XLabsIPAdapterExtension],
regional_prompting_extension: RegionalPromptingExtension,
) -> Tensor:
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))
if self.params.guidance_embed:
if guidance is None:
raise ValueError("Didn't get guidance strength for guidance distilled model.")
vec = vec + self.guidance_in(timestep_embedding(guidance, 256))
vec = vec + self.vector_in(y)
txt = self.txt_in(txt)
ids = torch.cat((txt_ids, img_ids), dim=1)
pe = self.pe_embedder(ids)
# Validate double_block_residuals shape.
if controlnet_double_block_residuals is not None:
assert len(controlnet_double_block_residuals) == len(self.double_blocks)
for block_index, block in enumerate(self.double_blocks):View on GitHub (pinned to 0b6a024f2f)
Solutions
- Reshape img to (batch, seq_len, channels) — for Flux, pack latents first (2x2 patchify then rearrange to B, seq, C)
- Reshape txt to (batch, seq_len, embed_dim) from your text encoder output
- Add .unsqueeze(0) if you forgot the batch dimension
Example fix
// before img = vae.encode(image) # B,C,H,W model(img=img, txt=t5_embeddings, ...) // after img = pack_latents(vae.encode(image)) # B, seq, 64 model(img=img, txt=t5_embeddings, ...) # txt: B, seq, 4096
Defensive patterns
Strategy: validation
Validate before calling
assert img.ndim == 3 and txt.ndim == 3, f"img: {img.shape}, txt: {txt.shape} — both must be (batch, seq, channels)" Type guard
def is_rank3_tensor(t: torch.Tensor) -> bool:
return isinstance(t, torch.Tensor) and t.ndim == 3 Try / catch
try:
output = model(img=img, txt=txt, ...)
except ValueError as e:
if "must have 3 dimensions" in str(e):
img = img.flatten(2).transpose(1, 2) if img.ndim == 4 else img.unsqueeze(0)
txt = txt.unsqueeze(0) if txt.ndim == 2 else txt
output = model(img=img, txt=txt, ...)
else:
raise Prevention
- Pack VAE latents (2x2 patchify) before passing as img
- Squeeze token dims of text encoder output to (B, seq, C)
- Log tensor shapes at pipeline boundaries when debugging
When it happens
Trigger: Calling model.forward (or __call__) with img or txt shaped (B,C,H,W) instead of (B,seq,C); passing a text encoder output without flattening token dims; passing an unbatched (seq,C) tensor.
Common situations: Wiring a diffusers-style UNet pipeline to Flux directly; forgetting pack/unpack of latents (Flux works on packed 2x2 patch latents of shape B, seq, 64); custom pipelines passing VAE latents untransformed.
Understand the failure class
Background: Tensor shape mismatch errors ("must have shape", "expected shape ... got ..."): when tensor dimensions disagree with what an op or layer was told to expect — this error's family across 6 libraries.
Related errors
- Input img and txt tensors must have 3 dimensions.
- Input img and txt tensors must have 3 dimensions.
- Didn't get guidance strength for guidance distilled model.
- Control LoRAs cannot be used with FLUX Schnell
- fill_conditioning was provided, but the model is not a FLUX
AI-assisted analysis of invoke-ai/InvokeAI@0b6a024f2f (2026-08-29).
Data as JSON: /api/errors/c08e40b1c0467c91.
Report an issue: GitHub.