wavetermdev/waveterm · error
part %d: %w
Error message
part %d: %w
What it means
This is a wrapper error: when convertFileAIMessagePart fails while processing part i, ConvertAIMessageToAnthropicChatMessage re-wraps the underlying error as "part %d: %w", preserving the original cause (missing data, unsupported protocol/media type, validation failure) and attributing it to the specific part index.
Source
Thrown at pkg/aiusechat/anthropic/anthropic-convertmessage.go:482
}
var contentBlocks []anthropicMessageContentBlock
for i, part := range aiMsg.Parts {
switch part.Type {
case uctypes.AIMessagePartTypeText:
if part.Text == "" {
return nil, fmt.Errorf("part %d: text type requires non-empty text field", i)
}
contentBlocks = append(contentBlocks, anthropicMessageContentBlock{
Type: "text",
Text: part.Text,
})
case uctypes.AIMessagePartTypeFile:
block, err := convertFileAIMessagePart(part)
if err != nil {
return nil, fmt.Errorf("part %d: %w", i, err)
}
contentBlocks = append(contentBlocks, *block)
default:
return nil, fmt.Errorf("part %d: unsupported part type '%s'", i, part.Type)
}
}
return &anthropicChatMessage{
MessageId: aiMsg.MessageId,
Role: "user",
Content: contentBlocks,
}, nil
}
// hasInlineData checks if the part has data available for inline use (either Data field or data URL)
func hasInlineData(part uctypes.AIMessagePart) bool {
hasData := len(part.Data) > 0View on GitHub (pinned to a4447c1563)
Solutions
- Use errors.As/errors.Is on the wrapped error to identify the root cause for the reported part index
- Inspect aiMsg.Parts[i] — confirm Type, Data/URL, and MimeType are consistent
- Fix the underlying cause per the inner error (add base64 data, use data: URL, correct media type)
- Pre-validate each file part (part.Validate() plus URL-scheme check) before conversion
Example fix
// before
msg, err := ConvertAIMessageToNativeChatMessage(aiMsg) // "part 2: no data available..."
// after
if err != nil {
var idx int
if _, e := fmt.Sscanf(err.Error(), "part %d:", &idx); e == nil {
log.Printf("bad part %d: %+v", idx, aiMsg.Parts[idx])
}
} Defensive patterns
Strategy: try-catch
Validate before calling
for i, p := range aiMsg.Parts {
if p.Type == uctypes.AIMessagePartTypeFile {
if err := p.Validate(); err != nil { return fmt.Errorf("part %d: %w", i, err) }
}
} Type guard
func filePartReady(p uctypes.AIMessagePart) bool {
return p.Type == uctypes.AIMessagePartTypeFile && p.Validate() == nil &&
(len(p.Data) > 0 || p.URL == "" || strings.HasPrefix(p.URL, "data:") || strings.HasPrefix(p.URL, "http"))
} Try / catch
out, err := ConvertAIMessageToNativeChatMessage(aiMsg)
if err != nil {
var partErr struct{ idx int }
if n, _ := fmt.Sscanf(err.Error(), "part %d:", &partErr.idx); n == 1 {
log.Printf("part %d failed: %v — dropping it", partErr.idx, err)
return convertWithoutPart(aiMsg, partErr.idx)
}
return err
} Prevention
- Pre-validate every file part (Validate + URL scheme + inline data presence)
- Parse the "part %d:" prefix to pinpoint and drop bad parts
- Keep attachments to supported schemes (data:, http:, https:)
When it happens
Trigger: Any AIMessagePart with Type file that fails inside convertFileAIMessagePart: Validate() failure, non-data:/http(s) URL scheme, no inline data for image/pdf, base64 extraction failure, etc., when called via ConvertAIMessageToAnthropicChatMessage.
Common situations: Debugging a batch-converted message and needing to know which attachment is bad; files with no Data and a non-data URL (e.g. https URL for pdf without inline data in contexts requiring it); parts built from untrusted input.
Related errors
- convertFileUIMessagePart expects 'file' type, got '%s'
- unsupported URL protocol in file part: %s
- failed to decode base64 data: %w
- dropping text/plain file with URL (must be fetched and conve
- dropping file with unsupported media type '%s' (must be uplo
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/5260fdf7549d358b.
Report an issue: GitHub.