{"record":{"id":"7ce950ac6919c29a","repo":"wavetermdev/waveterm","slug":"part-d-text-type-requires-non-empty-text-field-7ce950","errorCode":null,"errorMessage":"part %d: text type requires non-empty text field","messagePattern":"part (.+?): text type requires non-empty text field","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/openai/openai-convertmessage.go","lineNumber":413,"sourceCode":"}\n\n// ConvertAIMessageToOpenAIChatMessage converts an AIMessage to OpenAIChatMessage\n// These messages are ALWAYS role \"user\"\n// Handles text parts, images, PDFs, and text/plain files\nfunc ConvertAIMessageToOpenAIChatMessage(aiMsg uctypes.AIMessage) (*OpenAIChatMessage, error) {\n\tif err := aiMsg.Validate(); err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid AIMessage: %w\", err)\n\t}\n\n\tvar contentBlocks []OpenAIMessageContent\n\timageCount := 0\n\timageFailCount := 0\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, OpenAIMessageContent{\n\t\t\t\tType: \"input_text\",\n\t\t\t\tText: part.Text,\n\t\t\t})\n\n\t\tcase uctypes.AIMessagePartTypeFile:\n\t\t\tif strings.HasPrefix(part.MimeType, \"image/\") {\n\t\t\t\timageCount++\n\t\t\t}\n\t\t\tblock, err := convertFileAIMessagePart(part)\n\t\t\tif err != nil {\n\t\t\t\tif strings.HasPrefix(part.MimeType, \"image/\") {\n\t\t\t\t\timageFailCount++\n\t\t\t\t}\n\t\t\t\tlog.Printf(\"openai: %v\", err)\n\t\t\t\tcontinue\n\t\t\t}","sourceCodeStart":395,"sourceCodeEnd":431,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/openai/openai-convertmessage.go#L395-L431","documentation":"When converting message parts, a text-type part with an empty Text field would produce a useless empty input_text content block, so the converter rejects it with this error naming the offending part index. OpenAI requires text content to be non-empty.","triggerScenarios":"An AIMessage passed to ConvertAIMessageToOpenAIChatMessage contains a part with Type == uctypes.AIMessagePartTypeText and part.Text == \"\".","commonSituations":"Building user messages from form input without checking for empty strings; trimming that reduces text to \"\"; appending placeholder text parts meant to be filled in later.","solutions":["Skip or drop empty text parts before calling the converter","Replace empty text with placeholder content if the part is required","Add a pre-call check on aiMsg.Parts that removes parts where Type==text && Text==\"\""],"exampleFix":"// before\nparts := []uctypes.AIMessagePart{{Type: uctypes.AIMessagePartTypeText, Text: \"\"}}\n// after\nparts := []uctypes.AIMessagePart{}\nfor _, p := range parts {\n    if p.Type == uctypes.AIMessagePartTypeText && p.Text == \"\" { continue }\n    parts = append(parts, p)\n}","handlingStrategy":"validation","validationCode":"for i, p := range aiMsg.Parts {\n    if p.Type == uctypes.AIMessagePartTypeText && p.Text == \"\" {\n        return fmt.Errorf(\"part %d has empty text\", i)\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Trim and check text before creating text parts","Skip empty parts when assembling messages","Sanitize user input before building AIMessage"],"tags":["validation","openai","empty-text"],"backgroundTag":"empty-required-field","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}