{"record":{"id":"e38487dc5c8f55ac","repo":"wavetermdev/waveterm","slug":"text-type-requires-non-empty-text-field","errorCode":null,"errorMessage":"text type requires non-empty text field","messagePattern":"text type requires non-empty text field","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/uctypes/uctypes.go","lineNumber":400,"sourceCode":"\t}\n\n\tif len(m.Parts) == 0 {\n\t\treturn fmt.Errorf(\"parts must not be empty\")\n\t}\n\n\tfor i, part := range m.Parts {\n\t\tif err := part.Validate(); err != nil {\n\t\t\treturn fmt.Errorf(\"part %d: %w\", i, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (p *AIMessagePart) Validate() error {\n\tif p.Type == AIMessagePartTypeText {\n\t\tif p.Text == \"\" {\n\t\t\treturn fmt.Errorf(\"text type requires non-empty text field\")\n\t\t}\n\t\t// Check that no file fields are set\n\t\tif p.FileName != \"\" || p.MimeType != \"\" || len(p.Data) > 0 || p.URL != \"\" {\n\t\t\treturn fmt.Errorf(\"text type cannot have file fields set\")\n\t\t}\n\t\treturn nil\n\t}\n\n\tif p.Type == AIMessagePartTypeFile {\n\t\tif p.Text != \"\" {\n\t\t\treturn fmt.Errorf(\"file type cannot have text field set\")\n\t\t}\n\n\t\tif p.MimeType == \"\" {\n\t\t\treturn fmt.Errorf(\"file type requires mimetype\")\n\t\t}\n\n\t\t// Either data or url (not both) must be set","sourceCodeStart":382,"sourceCodeEnd":418,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/uctypes/uctypes.go#L382-L418","documentation":"AIMessagePart.Validate() rejects a part whose Type is \"text\" but whose Text field is empty. A text part must carry actual prompt content; an empty text part would serialize to a meaningless message part sent to the AI backend.","triggerScenarios":"Calling part.Validate() or AIMessage.Validate() on an AIMessagePart with Type \"text\" (AIMessagePartTypeText) and Text == \"\", e.g. a POSTed AIMessage JSON like {\"type\":\"text\"} with no text field.","commonSituations":"Frontend sends a message with an empty input box; client code builds a text part but forgets to assign Text; a form submission trims user input to empty before constructing the part.","solutions":["Ensure the Text field is populated with non-empty content before validating","Skip adding the part entirely when there is no text content","Check the client JSON payload uses the \"text\" key so the field unmarshals correctly"],"exampleFix":"// before\npart := uctypes.AIMessagePart{Type: uctypes.AIMessagePartTypeText}\n// after\nif input != \"\" {\n\tpart := uctypes.AIMessagePart{Type: uctypes.AIMessagePartTypeText, Text: input}\n}","handlingStrategy":"validation","validationCode":"func validTextPart(p uctypes.AIMessagePart) bool {\n\treturn p.Type == uctypes.AIMessagePartTypeText && p.Text != \"\"\n}","typeGuard":"func isTextPart(p uctypes.AIMessagePart) (string, bool) {\n\tif p.Type == uctypes.AIMessagePartTypeText && p.Text != \"\" {\n\t\treturn p.Text, true\n\t}\n\treturn \"\", false\n}","tryCatchPattern":null,"preventionTips":["Only construct a text part when you have non-empty text","Validate user input (trim and check) before building parts","Call part.Validate() locally before POSTing the AIMessage"],"tags":["validation","ai-messages"],"backgroundTag":"schema-validation-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}