wavetermdev/waveterm · error
text/plain file part missing data
Error message
text/plain file part missing data
What it means
Indicates a text/plain file part in an AI message is missing its data payload, so the file cannot be attached or converted.
Source
Thrown at pkg/aiusechat/aiutil/aiutil.go:100
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)
}
// FormatAttachedDirectoryListing formats a directory listing attachment with proper encoding and deterministic suffix
func FormatAttachedDirectoryListing(directoryName, jsonContent string) string {View on GitHub (pinned to a4447c1563)
Solutions
- Read the text file and pass its bytes as the data argument.
- Populate the URL field with a data: URL containing the text content.
- Skip the empty part and warn instead of calling ExtractTextData with no content.
- Add a pre-check: if len(data) == 0 && url == "" return/skip the part early.
Example fix
// before
part := uctypes.UIMessageDataUserFile{FileName: "a.txt", MimeType: "text/plain"}
_, err := aiutil.ExtractTextData(nil, "") // missing data
// after
content, _ := os.ReadFile("a.txt")
_, err := aiutil.ExtractTextData(content, "") Defensive patterns
Strategy: validation
Validate before calling
func hasTextContent(data []byte, url string) bool { return len(data) > 0 || url != "" }
if !hasTextContent(part.Data, part.URL) { return fmt.Errorf("text file %q has no content", part.FileName) } Try / catch
content, err := aiutil.ExtractTextData(data, url)
if err != nil {
return nil, fmt.Errorf("attachment %s unusable, skipping: %w", fileName, err)
} Prevention
- Verify Data or URL is populated before building text file parts
- Check serialization round-trips preserve the Data field
- Reject empty attachments at the ingestion boundary with a user-facing warning
When it happens
Trigger: Calling ExtractTextData (directly or via convertFileAIMessagePart/convertAIMessageTextOnly/convertAIMessageMultimodal) with data == nil/empty AND url == "" — e.g. a file part where only FileName/MimeType were set.
Common situations: Constructing UIMessageParts for text attachments without reading the file; content lost during serialization/deserialization; a client that sent the attachment metadata but failed to include the body.
Related errors
- integer overflow
- file part missing both url and data
- failed to decode data URL for text/plain file: %w
- dropping text/plain file with URL (must be fetched and conve
- input is required
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/a7591ced266d90d6.
Report an issue: GitHub.