wavetermdev/waveterm · error

all %d image conversions failed

Error message

all %d image conversions failed

What it means

After processing all parts, if every content block was an image and every image failed to convert (imageFailCount == imageCount), the message would have no usable content, so the converter returns this error reporting how many images failed. It distinguishes total image-conversion failure from the generic 'no valid content' case.

Source

Thrown at pkg/aiusechat/openai/openai-convertmessage.go:443

			if err != nil {
				if strings.HasPrefix(part.MimeType, "image/") {
					imageFailCount++
				}
				log.Printf("openai: %v", err)
				continue
			}
			contentBlocks = append(contentBlocks, *block)

		default:
			// Drop unknown part types
			log.Printf("openai: dropping unknown part type '%s'", part.Type)
			continue
		}
	}

	if len(contentBlocks) == 0 {
		if imageCount > 0 && imageFailCount == imageCount {
			return nil, fmt.Errorf("all %d image conversions failed", imageCount)
		}
		return nil, errors.New("message has no valid content after processing all parts")
	}

	return &OpenAIChatMessage{
		MessageId: aiMsg.MessageId,
		Message: &OpenAIMessage{
			Role:    "user",
			Content: contentBlocks,
		},
	}, nil
}

// ConvertToolResultsToOpenAIChatMessage converts AIToolResult slice to OpenAIChatMessage slice
func ConvertToolResultsToOpenAIChatMessage(toolResults []uctypes.AIToolResult) ([]*OpenAIChatMessage, error) {
	if len(toolResults) == 0 {
		return nil, errors.New("toolResults cannot be empty")
	}

View on GitHub (pinned to a4447c1563)

Solutions

  1. Log the per-image conversion failures (the loop counts imageFailCount) to find the root cause
  2. Validate/decode image data before adding image parts to the AIMessage
  3. Include at least one text part alongside images so a single image failure doesn't void the message
  4. Re-encode the images to a supported format (e.g. PNG/JPEG base64 data URL)

Example fix

// before
msg := uctypes.AIMessage{Parts: []uctypes.AIMessagePart{{Type: uctypes.AIMessagePartTypeImage, /* corrupt data */}}}
// after
msg := uctypes.AIMessage{Parts: []uctypes.AIMessagePart{
    {Type: uctypes.AIMessagePartTypeText, Text: "describe the image"},
    {Type: uctypes.AIMessagePartTypeImage, /* valid base64 data */},
}}
Defensive patterns

Strategy: fallback

Validate before calling

validImages := 0
for _, p := range aiMsg.Parts {
    if p.Type == uctypes.AIMessagePartTypeImage && imageDecodes(p) { validImages++ }
}

Try / catch

out, err := ConvertAIMessageToOpenAIChatMessage(msg)
if err != nil && strings.Contains(err.Error(), "image conversions failed") {
    // fall back to a text-only message or surface image errors to the user
}

Prevention

When it happens

Trigger: An AIMessage containing only image parts where each image part fails conversion (e.g. unreadable/invalid image data, unsupported format, failed base64/data-URL decode), leaving len(contentBlocks)==0.

Common situations: Sending corrupt or truncated image files; images whose data URLs are malformed; image sources that failed to load upstream so the bytes are empty; unsupported encodings after a library upgrade.

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/e4d43ceec4280270. Report an issue: GitHub.