wavetermdev/waveterm · error
text/plain file with URL not supported (must be fetched and
Error message
text/plain file with URL not supported (must be fetched and converted to base64 or uploaded to Files API)
What it means
Anthropic document blocks for text/plain content require inline base64 data or a Files API file_id; the library does not fetch remote URLs on the caller's behalf. A text/plain part that carries an http/https URL instead of embedded data is rejected because there is no inline content to send.
Source
Thrown at pkg/aiusechat/anthropic/anthropic-convertmessage.go:649
}
decoded, err := base64.StdEncoding.DecodeString(base64Data)
if err != nil {
return nil, fmt.Errorf("failed to decode base64 data: %w", err)
}
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{View on GitHub (pinned to a4447c1563)
Solutions
- Fetch the URL yourself (http.Get), read the body, base64-encode it, and supply it as a data: URL
- Upload the file to the Anthropic Files API and reference it by file_id
- Inline the text content directly as base64 data in the part
Example fix
// before part.URL = "https://example.com/notes.txt" // after resp, _ := http.Get(part.URL) body, _ := io.ReadAll(resp.Body) part.URL = "data:text/plain;base64," + base64.StdEncoding.EncodeToString(body)
Defensive patterns
Strategy: fallback
Validate before calling
if strings.HasPrefix(part.MimeType, "text/plain") && strings.HasPrefix(part.URL, "http") && !strings.HasPrefix(part.URL, "data:") {
// fetch and convert to base64 first
} Try / catch
blocks, err := anthropic.ConvertAIMessageToAnthropicChatMessage(msg)
if err != nil && strings.Contains(err.Error(), "text/plain file with URL not supported") {
body := fetchAndBase64(part.URL) // fallback: fetch yourself
part.URL = "data:text/plain;base64," + body
} Prevention
- Never pass remote text URLs directly; pre-fetch them
- Prefer data: URLs or Files API uploads for non-image content
- Document supported input forms for text parts in your API layer
When it happens
Trigger: ConvertFileAIMessagePart with a part whose MimeType starts with 'text/plain' and part.URL is an http:// or https:// URL (rather than a data: URL) and no base64 data is provided.
Common situations: Passing a link to a hosted text/CSV/log file expecting the SDK to download it; migrating code from another provider that fetched URLs server-side.
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/9af389d080566b5a.
Report an issue: GitHub.