wavetermdev/waveterm · error

unsupported media type '%s' (must be uploaded to Files API a

Error message

unsupported media type '%s' (must be uploaded to Files API and sent as file_id)

What it means

The Anthropic inline conversion path only supports image/*, application/pdf, and text/plain mimetypes. Any other media type (audio, video, office docs, etc.) cannot be sent inline and must be uploaded to the Anthropic Files API and referenced by file_id, so conversion fails with this message.

Source

Thrown at pkg/aiusechat/anthropic/anthropic-convertmessage.go:654

				textData = string(decoded)
			}
			return &anthropicMessageContentBlock{
				Type: "document",
				Source: &anthropicSource{
					Type:      "text",
					Data:      textData,
					MediaType: part.MimeType,
					FileName:  part.FileName,
				},
			}, nil
		} else {
			// HTTP/HTTPS URL → not supported inline, would need to fetch
			return nil, fmt.Errorf("text/plain file with URL not supported (must be fetched and converted to base64 or uploaded to Files API)")
		}

	default:
		// Other media types → not supported inline, must upload and use file_id
		return nil, fmt.Errorf("unsupported media type '%s' (must be uploaded to Files API and sent as file_id)", part.MimeType)
	}
}

// ConvertToUIMessage converts an anthropicChatMessage to a UIMessage
func (m *anthropicChatMessage) ConvertToUIMessage() *uctypes.UIMessage {
	var parts []uctypes.UIMessagePart

	// Iterate over all content blocks
	for _, block := range m.Content {
		switch block.Type {
		case "text":
			// Convert text blocks to UIMessagePart
			parts = append(parts, uctypes.UIMessagePart{
				Type: "text",
				Text: block.Text,
			})
		case "image":
			// Convert image blocks to data-userfile UIMessagePart (only for user role)

View on GitHub (pinned to a4447c1563)

Solutions

  1. Upload the file via the Anthropic Files API and pass the returned file_id instead of inline content
  2. Convert the file to a supported type (PDF, PNG/JPEG/etc., or plain text) before sending
  3. If the content is truly text, set MimeType to text/plain and supply base64 data

Example fix

// before
part := uctypes.AIMessagePart{MimeType: "audio/wav", URL: dataURL}
// after
file, _ := client.Files.Upload(ctx, wavData, "audio/wav", "clip.wav")
part := uctypes.AIMessagePart{MimeType: "audio/wav", FileID: file.ID}
Defensive patterns

Strategy: validation

Validate before calling

func inlineSupported(mime string) bool {
    return strings.HasPrefix(mime, "image/") || mime == "application/pdf" || strings.HasPrefix(mime, "text/plain")
}
if !inlineSupported(part.MimeType) { /* upload to Files API first */ }

Type guard

func isInlinableMime(mime string) bool {
    return strings.HasPrefix(mime, "image/") || mime == "application/pdf" || strings.HasPrefix(mime, "text/plain")
}

Prevention

When it happens

Trigger: ConvertFileAIMessagePart (via ConvertAIMessageToAnthropicChatMessage) with a file part whose MimeType is not image/*, application/pdf, or text/plain/* — e.g. 'audio/mpeg', 'application/zip', 'video/mp4'.

Common situations: Attaching audio/video recordings or arbitrary binary attachments to a chat message; assuming the SDK supports the same media types as other AI providers.

Related errors


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