wavetermdev/waveterm · error

file part missing mediaType

Error message

file part missing mediaType

What it means

After the URL check, convertFileUIMessagePart requires p.MediaType to decide the Anthropic block shape: image/* becomes an image block, application/pdf and text/plain become document blocks. Without MediaType the converter cannot choose a block type, so it errors with 'file part missing mediaType'.

Source

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

			log.Printf("anthropic: %v", err)
			continue
		}
		blocks = append(blocks, partBlocks...)
	}

	return blocks, nil
}

// convertFileUIMessagePart converts a file part to Anthropic image or document block format
func convertFileUIMessagePart(p uctypes.UIMessagePart) (*anthropicMessageContentBlock, error) {
	if p.Type != "file" {
		return nil, fmt.Errorf("convertFileUIMessagePart expects 'file' type, got '%s'", p.Type)
	}
	if p.URL == "" {
		return nil, errors.New("file part missing url")
	}
	if p.MediaType == "" {
		return nil, errors.New("file part missing mediaType")
	}

	// Validate URL protocol - only allow data:, http:, https:
	if !strings.HasPrefix(p.URL, "data:") &&
		!strings.HasPrefix(p.URL, "http://") &&
		!strings.HasPrefix(p.URL, "https://") {
		return nil, fmt.Errorf("unsupported URL protocol in file part: %s", p.URL)
	}

	// Branch on mediaType first to determine block type and constraints
	switch {
	case strings.HasPrefix(p.MediaType, "image/"):
		// image/* (jpeg, png, gif, webp) → Anthropic image block
		if strings.HasPrefix(p.URL, "data:") {
			// Data URL → base64 source
			parts := strings.SplitN(p.URL, ",", 2)
			if len(parts) != 2 {
				return nil, errors.New("invalid data URL format")

View on GitHub (pinned to a4447c1563)

Solutions

  1. Set p.MediaType (e.g. "image/png", "application/pdf", "text/plain") on the file part.
  2. Infer the MIME type from the file extension or response Content-Type before sending.
  3. Drop or convert unsupported media-type-less parts before the chat call.

Example fix

// before
part := uctypes.UIMessagePart{Type: "file", URL: dataURL}

// after
part := uctypes.UIMessagePart{Type: "file", URL: dataURL, MediaType: "image/png"}
Defensive patterns

Strategy: validation

Validate before calling

if p.Type == "file" && p.MediaType == "" {
    return fmt.Errorf("file part %s requires mediaType", p.URL)
}

Type guard

func hasMediaType(p uctypes.UIMessagePart) bool {
    return p.Type != "file" || p.MediaType != ""
}

Try / catch

blocks, err := convertPartToAnthropicBlocks(part)
if err != nil && strings.Contains(err.Error(), "file part missing mediaType") {
    return fmt.Errorf("set MediaType from file extension or Content-Type: %w", err)
}

Prevention

When it happens

Trigger: A file part with a non-empty URL but MediaType == "" passed into convertPartToAnthropicBlocks, e.g. a URL-only attachment where the client never recorded the MIME type.

Common situations: Constructing parts from raw URLs fetched at runtime without sniffing the content type; older client payloads predating the mediaType field; hand-built message fixtures in tests.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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