wavetermdev/waveterm · warning
dropping text/plain file with URL (must be fetched and conve
Error message
dropping text/plain file with URL (must be fetched and converted to data)
What it means
ExtractTextData only accepts text content as raw bytes or as a data: URL. If the url is a remote reference (http/https or other scheme) the function refuses to process it because it does not fetch network resources. The text file is effectively 'dropped' from the message.
Source
Thrown at pkg/aiusechat/aiutil/aiutil.go:98
return fmt.Sprintf("data:%s;base64,%s", mimeType, base64Data), nil
}
return "", fmt.Errorf("file part missing both url and data")
}
// ExtractTextData extracts text data from either Data field or URL field (data: URLs only)
func ExtractTextData(data []byte, url string) ([]byte, error) {
if len(data) > 0 {
return data, nil
}
if url != "" {
if strings.HasPrefix(url, "data:") {
_, decodedData, err := utilfn.DecodeDataURL(url)
if err != nil {
return nil, fmt.Errorf("failed to decode data URL for text/plain file: %w", err)
}
return decodedData, nil
}
return nil, fmt.Errorf("dropping text/plain file with URL (must be fetched and converted to data)")
}
return nil, fmt.Errorf("text/plain file part missing data")
}
// FormatAttachedTextFile formats a text file attachment with proper encoding and deterministic suffix
func FormatAttachedTextFile(fileName string, textContent []byte) string {
if fileName == "" {
fileName = "untitled.txt"
}
encodedFileName := strings.ReplaceAll(fileName, `"`, """)
quotedFileName := strconv.Quote(encodedFileName)
textStr := string(textContent)
deterministicSuffix := GenerateDeterministicSuffix(textStr, fileName)
return fmt.Sprintf("<AttachedTextFile_%s file_name=%s>\n%s\n</AttachedTextFile_%s>", deterministicSuffix, quotedFileName, textStr, deterministicSuffix)
}
View on GitHub (pinned to a4447c1563)
Solutions
- Fetch the URL yourself (http.Get or equivalent) and pass the response bytes via the data parameter.
- Convert the fetched bytes to a data: URL before passing, if you must keep the URL parameter shape.
- Change the client to upload the text content inline (base64 data URL) instead of sending a link.
- Handle the error by dropping the attachment and appending a note to the message text.
Example fix
// before
content, err := aiutil.ExtractTextData(nil, "https://example.com/notes.txt") // dropped
// after
resp, _ := http.Get("https://example.com/notes.txt")
body, _ := io.ReadAll(resp.Body)
content, err := aiutil.ExtractTextData(body, "") Defensive patterns
Strategy: fallback
Validate before calling
func needsFetch(u string) bool { return u != "" && !strings.HasPrefix(u, "data:") } Type guard
func isDataURL(u string) bool { return strings.HasPrefix(u, "data:") } Try / catch
content, err := aiutil.ExtractTextData(data, url)
if err != nil && strings.Contains(err.Error(), "dropping text/plain") {
resp, ferr := http.Get(url)
if ferr == nil {
body, _ := io.ReadAll(resp.Body)
content, err = aiutil.ExtractTextData(body, "")
}
} Prevention
- Fetch remote text URLs into bytes before attaching them to messages
- Prefer inline data: URLs for text files in client integrations
- Document to frontend authors that text attachments must carry content, not links
When it happens
Trigger: Passing ExtractTextData a URL like "https://example.com/notes.txt" or any non-data: URL with empty data. Callers (convertFileAIMessagePart, convertAIMessageTextOnly, convertAIMessageMultimodal) hit this when an attached text file part carries a remote URL instead of inline content.
Common situations: Client uploads a file reference/link rather than file content; frontend integration forwards a CDN URL for text files; migrating from providers that accept remote file URLs to this message format that requires inline data.
Related errors
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/527b2885637c03d2.
Report an issue: GitHub.