{"record":{"id":"2dd4a0d5ca2f1843","repo":"wavetermdev/waveterm","slug":"invalid-url-w","errorCode":null,"errorMessage":"invalid url: %w","messagePattern":"invalid url: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/aiusechat/uctypes/uctypes.go","lineNumber":434,"sourceCode":"\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}\n\n// ---------------------\n// AI SDK Streaming Protocol\n\n// Type can be one of these consts...\n// text-start, text-delta, text-end,\n// reasoning-start, reasoning-delta, reasoning-end,","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/aiusechat/uctypes/uctypes.go#L416-L452","documentation":"Wrapped validation error: the URL on a file-type part failed url.Parse-based validation. Wraps the parse error.","triggerScenarios":"AIMessagePart{Type:\"file\", MimeType:..., URL: \"ht!tp://x\"} or other malformed URL (control characters, bad percent-encoding) passed to Validate().","commonSituations":"User-supplied attachment URLs passed through unvalidated; concatenation bugs producing broken URLs (missing scheme, stray spaces); storing relative paths in the URL field.","solutions":["Fix the URL string so it parses (correct scheme, encoding)","If the value is a local path, upload/serve it and store a full https:// URL instead","For inline small files use a data: URL, e.g. data:image/png;base64,..."],"exampleFix":"// before\npart := uctypes.AIMessagePart{Type: \"file\", MimeType: \"image/png\", URL: \"example.com/a.png\"}\n// after\npart := uctypes.AIMessagePart{Type: \"file\", MimeType: \"image/png\", URL: \"https://example.com/a.png\"}","handlingStrategy":"validation","validationCode":"func parseableURL(raw string) bool {\n\t_, err := url.Parse(raw)\n\treturn err == nil\n}","typeGuard":"func validFileURL(p uctypes.AIMessagePart) (*url.URL, bool) {\n\tif p.Type != uctypes.AIMessagePartTypeFile || p.URL == \"\" {\n\t\treturn nil, false\n\t}\n\tu, err := url.Parse(p.URL)\n\tif err != nil {\n\t\treturn nil, false\n\t}\n\treturn u, true\n}","tryCatchPattern":null,"preventionTips":["url.Parse the string before assigning it to the URL field","Never store local paths or relative paths in the URL field","Percent-encode user-supplied URL components with url.PathEscape"],"tags":["validation","url","ai-messages"],"backgroundTag":"invalid-url","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}