{"record":{"id":"bb574925904e61aa","repo":"wavetermdev/waveterm","slug":"no-data-available-for-base64-extraction","errorCode":null,"errorMessage":"no data available for base64 extraction","messagePattern":"no data available for base64 extraction","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/anthropic/anthropic-convertmessage.go","lineNumber":533,"sourceCode":"\t\tparts := strings.SplitN(part.URL, \",\", 2)\n\t\tif len(parts) != 2 {\n\t\t\treturn \"\", errors.New(\"invalid data URL format\")\n\t\t}\n\n\t\theader := parts[0]\n\t\tdata := parts[1]\n\n\t\t// Check if it's already base64 encoded: data:mediatype;base64,<data>\n\t\tif strings.Contains(header, \";base64\") {\n\t\t\t// Already base64 encoded\n\t\t\treturn data, nil\n\t\t} else {\n\t\t\t// Raw data that needs base64 encoding: data:mediatype,<raw_data>\n\t\t\treturn base64.StdEncoding.EncodeToString([]byte(data)), nil\n\t\t}\n\t}\n\n\treturn \"\", errors.New(\"no data available for base64 extraction\")\n}\n\n// convertFileAIMessagePart converts a file AIMessagePart to anthropicMessageContentBlock\nfunc convertFileAIMessagePart(part uctypes.AIMessagePart) (*anthropicMessageContentBlock, error) {\n\tif part.Type != uctypes.AIMessagePartTypeFile {\n\t\treturn nil, fmt.Errorf(\"convertFileAIMessagePart expects 'file' type, got '%s'\", part.Type)\n\t}\n\n\tif err := part.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\n\t// Validate URL protocol if URL is provided - only allow data:, http:, https:\n\tif part.URL != \"\" {\n\t\tif !strings.HasPrefix(part.URL, \"data:\") &&\n\t\t\t!strings.HasPrefix(part.URL, \"http://\") &&\n\t\t\t!strings.HasPrefix(part.URL, \"https://\") {\n\t\t\treturn nil, fmt.Errorf(\"unsupported URL protocol in file part: %s\", part.URL)","sourceCodeStart":515,"sourceCodeEnd":551,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/anthropic/anthropic-convertmessage.go#L515-L551","documentation":"extractBase64Data in pkg/aiusechat/anthropic/anthropic-convertmessage.go builds base64-encoded media data for Anthropic message content blocks. It handles 'data:' URLs (base64 or raw payloads) and raw data, but if the input string yields no extractable data it falls through to this error. It signals that the file AI message part contained no usable data payload to encode.","triggerScenarios":"convertFileAIMessagePart receives an AIMessagePart of type 'file' whose Data (or equivalent data string) is empty, is a malformed data: URL with an empty payload (e.g. 'data:image/png,' with nothing after the comma and no raw fallback), or otherwise does not match any of the extraction branches, so the function reaches the trailing 'return \"\", errors.New(...)' at line 533.","commonSituations":"Frontend uploads a file attachment with metadata but the binary content was never populated; a data URL was truncated or hand-constructed incorrectly; a paste/screenshot capture produced an empty payload; middleware stripped the data field during message serialization.","solutions":["Check that the file AIMessagePart's data field is non-empty before adding the part to the AI message","Verify data: URLs are well formed: 'data:<mediatype>;base64,<payload>' with an actual base64 payload after the comma","Re-generate or re-capture the file content on the client side and resend the message","If the file is only available as a path or URL (not inline data), convert it to base64 first instead of passing it to convertFileAIMessagePart"],"exampleFix":"// before\npart := uctypes.AIMessagePart{Type: uctypes.AIMessagePartTypeFile, Data: dataUrl}\n// after\nif dataUrl == \"\" || !strings.Contains(dataUrl, \",\") {\n    return fmt.Errorf(\"file part %q has no data payload\", partName)\n}\npart := uctypes.AIMessagePart{Type: uctypes.AIMessagePartTypeFile, Data: dataUrl}","handlingStrategy":"validation","validationCode":"func filePartHasData(part uctypes.AIMessagePart) bool {\n    if part.Type != uctypes.AIMessagePartTypeFile || part.Data == \"\" {\n        return false\n    }\n    if strings.HasPrefix(part.Data, \"data:\") {\n        return strings.Contains(part.Data, \",\") && len(strings.SplitN(part.Data, \",\", 2)[1]) > 0\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate file part payloads at the client before attaching them to AI messages","Always construct data: URLs with a base64 payload, never a bare 'data:<mediatype>,' prefix","Log and skip empty file parts early in the conversion pipeline instead of passing them downstream"],"tags":["anthropic","base64","file-upload","message-conversion"],"backgroundTag":"missing-payload-in-file","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}