{"record":{"id":"9e8c4ba68a95c7ff","repo":"wavetermdev/waveterm","slug":"file-part-missing-mediatype","errorCode":null,"errorMessage":"file part missing mediaType","messagePattern":"file part missing mediaType","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/anthropic/anthropic-convertmessage.go","lineNumber":360,"sourceCode":"\t\t\tlog.Printf(\"anthropic: %v\", err)\n\t\t\tcontinue\n\t\t}\n\t\tblocks = append(blocks, partBlocks...)\n\t}\n\n\treturn blocks, nil\n}\n\n// convertFileUIMessagePart converts a file part to Anthropic image or document block format\nfunc convertFileUIMessagePart(p uctypes.UIMessagePart) (*anthropicMessageContentBlock, error) {\n\tif p.Type != \"file\" {\n\t\treturn nil, fmt.Errorf(\"convertFileUIMessagePart expects 'file' type, got '%s'\", p.Type)\n\t}\n\tif p.URL == \"\" {\n\t\treturn nil, errors.New(\"file part missing url\")\n\t}\n\tif p.MediaType == \"\" {\n\t\treturn nil, errors.New(\"file part missing mediaType\")\n\t}\n\n\t// Validate URL protocol - only allow data:, http:, https:\n\tif !strings.HasPrefix(p.URL, \"data:\") &&\n\t\t!strings.HasPrefix(p.URL, \"http://\") &&\n\t\t!strings.HasPrefix(p.URL, \"https://\") {\n\t\treturn nil, fmt.Errorf(\"unsupported URL protocol in file part: %s\", p.URL)\n\t}\n\n\t// Branch on mediaType first to determine block type and constraints\n\tswitch {\n\tcase strings.HasPrefix(p.MediaType, \"image/\"):\n\t\t// image/* (jpeg, png, gif, webp) → Anthropic image block\n\t\tif strings.HasPrefix(p.URL, \"data:\") {\n\t\t\t// Data URL → base64 source\n\t\t\tparts := strings.SplitN(p.URL, \",\", 2)\n\t\t\tif len(parts) != 2 {\n\t\t\t\treturn nil, errors.New(\"invalid data URL format\")","sourceCodeStart":342,"sourceCodeEnd":378,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/anthropic/anthropic-convertmessage.go#L342-L378","documentation":"After the URL check, convertFileUIMessagePart requires p.MediaType to decide the Anthropic block shape: image/* becomes an image block, application/pdf and text/plain become document blocks. Without MediaType the converter cannot choose a block type, so it errors with 'file part missing mediaType'.","triggerScenarios":"A file part with a non-empty URL but MediaType == \"\" passed into convertPartToAnthropicBlocks, e.g. a URL-only attachment where the client never recorded the MIME type.","commonSituations":"Constructing parts from raw URLs fetched at runtime without sniffing the content type; older client payloads predating the mediaType field; hand-built message fixtures in tests.","solutions":["Set p.MediaType (e.g. \"image/png\", \"application/pdf\", \"text/plain\") on the file part.","Infer the MIME type from the file extension or response Content-Type before sending.","Drop or convert unsupported media-type-less parts before the chat call."],"exampleFix":"// before\npart := uctypes.UIMessagePart{Type: \"file\", URL: dataURL}\n\n// after\npart := uctypes.UIMessagePart{Type: \"file\", URL: dataURL, MediaType: \"image/png\"}","handlingStrategy":"validation","validationCode":"if p.Type == \"file\" && p.MediaType == \"\" {\n    return fmt.Errorf(\"file part %s requires mediaType\", p.URL)\n}","typeGuard":"func hasMediaType(p uctypes.UIMessagePart) bool {\n    return p.Type != \"file\" || p.MediaType != \"\"\n}","tryCatchPattern":"blocks, err := convertPartToAnthropicBlocks(part)\nif err != nil && strings.Contains(err.Error(), \"file part missing mediaType\") {\n    return fmt.Errorf(\"set MediaType from file extension or Content-Type: %w\", err)\n}","preventionTips":["Record the MIME type at file-selection time, not at send time.","Use mime.TypeByExtension(filepath.Ext(name)) as a fallback when unknown.","Reject media-type-less attachments in message validation."],"tags":["validation","message-conversion","attachments"],"backgroundTag":"missing-required-argument","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}