wavetermdev/waveterm · error
convertFileUIMessagePart expects 'file' type, got '%s'
Error message
convertFileUIMessagePart expects 'file' type, got '%s'
What it means
convertFileUIMessagePart is an internal dispatcher that only handles UIMessageParts whose Type is exactly "file". The library throws this error when a caller (via convertPartToAnthropicBlocks) routes a part of a different type into the file conversion path, indicating an internal mis-dispatch or a caller constructing parts with a wrong/empty Type field. It is a defensive type check, not a data-content validation.
Source
Thrown at pkg/aiusechat/anthropic/anthropic-convertmessage.go:354
func convertPartsToAnthropicBlocks(parts []uctypes.UIMessagePart, role string) ([]anthropicMessageContentBlock, error) {
var blocks []anthropicMessageContentBlock
for _, p := range parts {
partBlocks, err := convertPartToAnthropicBlocks(p, role, len(blocks))
if err != nil {
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/"):View on GitHub (pinned to a4447c1563)
Solutions
- Set the part's Type field to "file" (uctypes.UIMessagePartTypeFile) before adding it to the message
- Check that your code routes only file parts into the file conversion path (fix the dispatch in convertPartToAnthropicBlocks callers)
- Log/inspect p.Type at the call site to find where the mis-typed part originates
Example fix
// before
part := uctypes.UIMessagePart{URL: "data:text/plain;base64,aGk=", MediaType: "text/plain"}
// after
part := uctypes.UIMessagePart{Type: "file", URL: "data:text/plain;base64,aGk=", MediaType: "text/plain"} Defensive patterns
Strategy: type-guard
Validate before calling
func isFileUIPart(p uctypes.UIMessagePart) bool { return p.Type == "file" }
if !isFileUIPart(p) { return fmt.Errorf("skipping non-file part %q", p.Type) } Type guard
func isFileUIPart(p uctypes.UIMessagePart) bool {
return p.Type == "file"
} Try / catch
block, err := convertFileUIMessagePart(p)
if err != nil {
if strings.Contains(err.Error(), "expects 'file' type") {
log.Printf("mis-typed part %q skipped", p.Type)
return nil, nil // skip
}
return nil, err
} Prevention
- Always set Type using the library's exported constants, never string literals
- Validate parts with the type's Validate() method before conversion
- Unit-test converters with all part types to catch dispatch bugs
When it happens
Trigger: Passing a UIMessagePart with Type set to something other than "file" (e.g. "text", "image", "", or a custom type) such that convertPartToAnthropicBlocks dispatches it to convertFileUIMessagePart.
Common situations: Building message parts by hand without setting Type; deserializing UI messages from JSON where the type discriminator was lost or renamed; a mapping bug in the caller that sends non-file parts down the file branch.
Related errors
- convertFileAIMessagePart expects 'file' type, got '%s'
- invalid AIMessage: %w
- part %d: unsupported part type '%s'
- no data available for base64 extraction
- toolResults cannot be empty
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/a7a9a59e4068ceb0.
Report an issue: GitHub.