{"record":{"id":"6d779067cc7b1014","repo":"invoke-ai/InvokeAI","slug":"expected-torch-tensor-for-prompt-embeddings-got","errorCode":null,"errorMessage":"Expected torch.Tensor for prompt embeddings, got {type(prompt_embeds).__name__}. Text encoder returned unexpected type.","messagePattern":"Expected torch\\.Tensor for prompt embeddings, got (.+?)\\. Text encoder returned unexpected type\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"invokeai/app/invocations/z_image_text_encoder.py","lineNumber":194,"sourceCode":"                raise RuntimeError(\n                    \"Text encoder did not return hidden_states. \"\n                    \"Ensure output_hidden_states=True is supported by this model.\"\n                )\n            if len(outputs.hidden_states) < 2:\n                raise RuntimeError(\n                    f\"Expected at least 2 hidden states from text encoder, got {len(outputs.hidden_states)}. \"\n                    \"This may indicate an incompatible model or configuration.\"\n                )\n            prompt_embeds = outputs.hidden_states[-2]\n\n            # Z-Image expects a 2D tensor [seq_len, hidden_dim] with only valid tokens\n            # Based on diffusers ZImagePipeline implementation:\n            # embeddings_list.append(prompt_embeds[i][prompt_masks[i]])\n            # Since batch_size=1, we take the first item and filter by mask\n            prompt_embeds = prompt_embeds[0][prompt_mask[0]]\n\n        if not isinstance(prompt_embeds, torch.Tensor):\n            raise TypeError(\n                f\"Expected torch.Tensor for prompt embeddings, got {type(prompt_embeds).__name__}. \"\n                \"Text encoder returned unexpected type.\"\n            )\n        return prompt_embeds\n\n    def _lora_iterator(self, context: InvocationContext) -> Iterator[PatchSpec]:\n        \"\"\"Iterate over LoRA models to apply to the Qwen3 text encoder.\"\"\"\n        for lora in self.qwen3_encoder.loras:\n            lora_info = context.models.load(lora.lora)\n            if not isinstance(lora_info.model, ModelPatchRaw):\n                raise TypeError(\n                    f\"Expected ModelPatchRaw for LoRA '{lora.lora.key}', got {type(lora_info.model).__name__}. \"\n                    \"The LoRA model may be corrupted or incompatible.\"\n                )\n            yield (lora_info.model, lora.weight, lora_info.model_in_ram())\n","sourceCodeStart":176,"sourceCodeEnd":210,"githubUrl":"https://github.com/invoke-ai/InvokeAI/blob/0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06/invokeai/app/invocations/z_image_text_encoder.py#L176-L210","documentation":"_encode_prompt in the Z-Image text encoder invocation expects the text encoder to return prompt embeddings as a torch.Tensor (after masking/batch-indexing). If the underlying encoder or pipeline path returns another type (list, tuple, nested tensors), this TypeError is thrown so downstream diffusion code never receives malformed embeddings. It is a defensive type check modeled on diffusers' ZImagePipeline expectations.","triggerScenarios":"Calling invoke() on the Z-Image text encoder when the text encoder output is not a torch.Tensor, e.g. an encoder wrapper returning a list of tensors, a tuple like (embeddings, attn_mask) that was not unpacked, or a mocked/stubbed encoder in tests returning a list.","commonSituations":"Using an incompatible or custom text-encoder implementation with the Z-Image pipeline; a diffusers version change altering the return type of encode_prompt; passing raw tokenizer output instead of encoded embeddings; batch/mask slicing producing a list when batch_size != 1 assumptions break.","solutions":["Inspect the actual return type of the text encoder (print(type(prompt_embeds))) at the call site and convert with torch.stack()/torch.cat() before calling _encode_prompt","Verify the diffusers ZImagePipeline version matches what InvokeAI expects; upgrade/downgrade diffusers so encode_prompt returns a Tensor","Ensure the mask-slicing path (prompt_embeds[0][prompt_mask[0]]) is applied to a Tensor, not to a list of per-item outputs","If using a custom encoder, wrap it so it returns a single torch.Tensor for the embeddings"],"exampleFix":"// before\nprompt_embeds = text_encoder(input_ids)  # returns list of tensors\n// after\nprompt_embeds = torch.stack(text_encoder(input_ids)) if isinstance(text_encoder_out, list) else text_encoder_out","handlingStrategy":"type-guard","validationCode":"import torch\nassert isinstance(prompt_embeds, torch.Tensor), f\"got {type(prompt_embeds).__name__}\"","typeGuard":"def is_tensor(x) -> bool:\n    import torch\n    return isinstance(x, torch.Tensor)","tryCatchPattern":"try:\n    embeds = invocation.invoke(context)\nexcept TypeError as e:\n    if 'prompt embeddings' in str(e):\n        prompt_embeds = torch.as_tensor(raw_output)\n    else:\n        raise","preventionTips":["Keep diffusers at the version InvokeAI pins","Always unpack tuple outputs from encoders before passing them along","Add a unit test asserting the encoder returns a Tensor"],"tags":["python","type-error","torch","text-encoder"],"backgroundTag":"unexpected-return-type","analyzedSha":"0b6a024f2ff6a86bfb953dcdb9cc504ef7397a06","analyzedAt":"2026-08-29T04:46:49.967Z","schemaVersion":2},"datasetVersion":"2026-08-29T07:17:48.351Z"}