{"record":{"id":"5260fdf7549d358b","repo":"wavetermdev/waveterm","slug":"part-d-w","errorCode":null,"errorMessage":"part %d: %w","messagePattern":"part (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/anthropic/anthropic-convertmessage.go","lineNumber":482,"sourceCode":"\t}\n\n\tvar contentBlocks []anthropicMessageContentBlock\n\n\tfor i, part := range aiMsg.Parts {\n\t\tswitch part.Type {\n\t\tcase uctypes.AIMessagePartTypeText:\n\t\t\tif part.Text == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"part %d: text type requires non-empty text field\", i)\n\t\t\t}\n\t\t\tcontentBlocks = append(contentBlocks, anthropicMessageContentBlock{\n\t\t\t\tType: \"text\",\n\t\t\t\tText: part.Text,\n\t\t\t})\n\n\t\tcase uctypes.AIMessagePartTypeFile:\n\t\t\tblock, err := convertFileAIMessagePart(part)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"part %d: %w\", i, err)\n\t\t\t}\n\t\t\tcontentBlocks = append(contentBlocks, *block)\n\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"part %d: unsupported part type '%s'\", i, part.Type)\n\t\t}\n\t}\n\n\treturn &anthropicChatMessage{\n\t\tMessageId: aiMsg.MessageId,\n\t\tRole:      \"user\",\n\t\tContent:   contentBlocks,\n\t}, nil\n}\n\n// hasInlineData checks if the part has data available for inline use (either Data field or data URL)\nfunc hasInlineData(part uctypes.AIMessagePart) bool {\n\thasData := len(part.Data) > 0","sourceCodeStart":464,"sourceCodeEnd":500,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/anthropic/anthropic-convertmessage.go#L464-L500","documentation":"This is a wrapper error: when convertFileAIMessagePart fails while processing part i, ConvertAIMessageToAnthropicChatMessage re-wraps the underlying error as \"part %d: %w\", preserving the original cause (missing data, unsupported protocol/media type, validation failure) and attributing it to the specific part index.","triggerScenarios":"Any AIMessagePart with Type file that fails inside convertFileAIMessagePart: Validate() failure, non-data:/http(s) URL scheme, no inline data for image/pdf, base64 extraction failure, etc., when called via ConvertAIMessageToAnthropicChatMessage.","commonSituations":"Debugging a batch-converted message and needing to know which attachment is bad; files with no Data and a non-data URL (e.g. https URL for pdf without inline data in contexts requiring it); parts built from untrusted input.","solutions":["Use errors.As/errors.Is on the wrapped error to identify the root cause for the reported part index","Inspect aiMsg.Parts[i] — confirm Type, Data/URL, and MimeType are consistent","Fix the underlying cause per the inner error (add base64 data, use data: URL, correct media type)","Pre-validate each file part (part.Validate() plus URL-scheme check) before conversion"],"exampleFix":"// before\nmsg, err := ConvertAIMessageToNativeChatMessage(aiMsg) // \"part 2: no data available...\"\n// after\nif err != nil {\n    var idx int\n    if _, e := fmt.Sscanf(err.Error(), \"part %d:\", &idx); e == nil {\n        log.Printf(\"bad part %d: %+v\", idx, aiMsg.Parts[idx])\n    }\n}","handlingStrategy":"try-catch","validationCode":"for i, p := range aiMsg.Parts {\n    if p.Type == uctypes.AIMessagePartTypeFile {\n        if err := p.Validate(); err != nil { return fmt.Errorf(\"part %d: %w\", i, err) }\n    }\n}","typeGuard":"func filePartReady(p uctypes.AIMessagePart) bool {\n    return p.Type == uctypes.AIMessagePartTypeFile && p.Validate() == nil &&\n        (len(p.Data) > 0 || p.URL == \"\" || strings.HasPrefix(p.URL, \"data:\") || strings.HasPrefix(p.URL, \"http\"))\n}","tryCatchPattern":"out, err := ConvertAIMessageToNativeChatMessage(aiMsg)\nif err != nil {\n    var partErr struct{ idx int }\n    if n, _ := fmt.Sscanf(err.Error(), \"part %d:\", &partErr.idx); n == 1 {\n        log.Printf(\"part %d failed: %v — dropping it\", partErr.idx, err)\n        return convertWithoutPart(aiMsg, partErr.idx)\n    }\n    return err\n}","preventionTips":["Pre-validate every file part (Validate + URL scheme + inline data presence)","Parse the \"part %d:\" prefix to pinpoint and drop bad parts","Keep attachments to supported schemes (data:, http:, https:)"],"tags":["go","error-wrapping","anthropic","file-part"],"backgroundTag":"part-conversion-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}