{"record":{"id":"9af389d080566b5a","repo":"wavetermdev/waveterm","slug":"text-plain-file-with-url-not-supported-must-be-fe","errorCode":null,"errorMessage":"text/plain file with URL not supported (must be fetched and converted to base64 or uploaded to Files API)","messagePattern":"text/plain file with URL not supported \\(must be fetched and converted to base64 or uploaded to Files API\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/anthropic/anthropic-convertmessage.go","lineNumber":649,"sourceCode":"\t\t\t\t}\n\t\t\t\tdecoded, err := base64.StdEncoding.DecodeString(base64Data)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"failed to decode base64 data: %w\", err)\n\t\t\t\t}\n\t\t\t\ttextData = string(decoded)\n\t\t\t}\n\t\t\treturn &anthropicMessageContentBlock{\n\t\t\t\tType: \"document\",\n\t\t\t\tSource: &anthropicSource{\n\t\t\t\t\tType:      \"text\",\n\t\t\t\t\tData:      textData,\n\t\t\t\t\tMediaType: part.MimeType,\n\t\t\t\t\tFileName:  part.FileName,\n\t\t\t\t},\n\t\t\t}, nil\n\t\t} else {\n\t\t\t// HTTP/HTTPS URL → not supported inline, would need to fetch\n\t\t\treturn nil, fmt.Errorf(\"text/plain file with URL not supported (must be fetched and converted to base64 or uploaded to Files API)\")\n\t\t}\n\n\tdefault:\n\t\t// Other media types → not supported inline, must upload and use file_id\n\t\treturn nil, fmt.Errorf(\"unsupported media type '%s' (must be uploaded to Files API and sent as file_id)\", part.MimeType)\n\t}\n}\n\n// ConvertToUIMessage converts an anthropicChatMessage to a UIMessage\nfunc (m *anthropicChatMessage) ConvertToUIMessage() *uctypes.UIMessage {\n\tvar parts []uctypes.UIMessagePart\n\n\t// Iterate over all content blocks\n\tfor _, block := range m.Content {\n\t\tswitch block.Type {\n\t\tcase \"text\":\n\t\t\t// Convert text blocks to UIMessagePart\n\t\t\tparts = append(parts, uctypes.UIMessagePart{","sourceCodeStart":631,"sourceCodeEnd":667,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/anthropic/anthropic-convertmessage.go#L631-L667","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\npart.URL = \"https://example.com/notes.txt\"\n// after\nresp, _ := http.Get(part.URL)\nbody, _ := io.ReadAll(resp.Body)\npart.URL = \"data:text/plain;base64,\" + base64.StdEncoding.EncodeToString(body)","handlingStrategy":"fallback","validationCode":"if strings.HasPrefix(part.MimeType, \"text/plain\") && strings.HasPrefix(part.URL, \"http\") && !strings.HasPrefix(part.URL, \"data:\") {\n    // fetch and convert to base64 first\n}","typeGuard":null,"tryCatchPattern":"blocks, err := anthropic.ConvertAIMessageToAnthropicChatMessage(msg)\nif err != nil && strings.Contains(err.Error(), \"text/plain file with URL not supported\") {\n    body := fetchAndBase64(part.URL) // fallback: fetch yourself\n    part.URL = \"data:text/plain;base64,\" + body\n}","preventionTips":["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"],"tags":["go","anthropic","unsupported-input","url-fetch"],"backgroundTag":"remote-url-not-supported","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}