{"record":{"id":"0f6c03d1db92a7e2","repo":"wavetermdev/waveterm","slug":"file-type-cannot-have-both-data-and-url-set","errorCode":null,"errorMessage":"file type cannot have both data and url set","messagePattern":"file type cannot have both data and url set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/uctypes/uctypes.go","lineNumber":427,"sourceCode":"\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\n\t\thasData := len(p.Data) > 0\n\t\thasURL := p.URL != \"\"\n\n\t\tif !hasData && !hasURL {\n\t\t\treturn fmt.Errorf(\"file type requires either data or url\")\n\t\t}\n\n\t\tif hasData && hasURL {\n\t\t\treturn fmt.Errorf(\"file type cannot have both data and url set\")\n\t\t}\n\n\t\t// If URL is set, validate it's https or data URL\n\t\tif hasURL {\n\t\t\tparsedURL, err := url.Parse(p.URL)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"invalid url: %w\", err)\n\t\t\t}\n\n\t\t\tif parsedURL.Scheme != \"https\" && parsedURL.Scheme != \"data\" {\n\t\t\t\treturn fmt.Errorf(\"url must be https or data URL, got %q\", parsedURL.Scheme)\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"type must be %q or %q, got %q\", AIMessagePartTypeText, AIMessagePartTypeFile, p.Type)\n}","sourceCodeStart":409,"sourceCodeEnd":445,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/uctypes/uctypes.go#L409-L445","documentation":"Validation error: a file-type message part sets both data and URL; they are mutually exclusive.","triggerScenarios":"AIMessagePart{Type:\"file\", MimeType:..., Data: data, URL: \"https://...\"} passed to Validate(); typically when a helper fills in the URL (e.g. a data: preview) while the caller also attached raw bytes.","commonSituations":"Code that auto-populates URL from uploaded data but keeps Data; merging partial updates where a URL was added to an already-inline attachment; copy-paste building parts from two examples.","solutions":["Remove the URL field and keep inline Data","Or remove Data and keep only URL (e.g. for large files)","Refactor the part-construction helper so it sets exactly one of Data/URL"],"exampleFix":"// before\npart := uctypes.AIMessagePart{Type: \"file\", MimeType: \"image/png\", Data: data, URL: \"https://example.com/a.png\"}\n// after\npart := uctypes.AIMessagePart{Type: \"file\", MimeType: \"image/png\", URL: \"https://example.com/a.png\"}","handlingStrategy":"validation","validationCode":"func singleContentSource(p uctypes.AIMessagePart) bool {\n\treturn len(p.Data) == 0 || p.URL == \"\" // at most one of data/url\n}","typeGuard":"func hasExactlyOneSource(p uctypes.AIMessagePart) bool {\n\tif p.Type != uctypes.AIMessagePartTypeFile {\n\t\treturn false\n\t}\n\treturn (len(p.Data) > 0) != (p.URL != \"\")\n}","tryCatchPattern":null,"preventionTips":["Pick one representation per file part: inline Data or URL","Make part-construction helpers take either data or url, never both","Prefer Data for small files, URL for large ones"],"tags":["validation","ai-messages","file-upload"],"backgroundTag":"schema-validation-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}