{"record":{"id":"23aeaa1071b77f81","repo":"sipeed/picoclaw","slug":"invalid-discord-proxy-url-q-w","errorCode":null,"errorMessage":"invalid discord proxy URL %q: %w","messagePattern":"invalid discord proxy URL %q: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/channels/discord/discord.go","lineNumber":776,"sourceCode":"\text := strings.ToLower(filepath.Ext(filename))\n\tswitch ext {\n\tcase \".jpg\", \".jpeg\", \".png\", \".gif\", \".webp\", \".bmp\":\n\t\treturn \"image\"\n\tcase \".mp3\", \".wav\", \".ogg\", \".m4a\", \".flac\", \".aac\", \".wma\":\n\t\treturn \"audio\"\n\tcase \".mp4\", \".avi\", \".mov\", \".webm\", \".mkv\":\n\t\treturn \"video\"\n\t}\n\n\treturn \"file\"\n}\n\nfunc applyDiscordProxy(session *discordgo.Session, proxyAddr string) error {\n\tvar proxyFunc func(*http.Request) (*url.URL, error)\n\tif proxyAddr != \"\" {\n\t\tproxyURL, err := url.Parse(proxyAddr)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"invalid discord proxy URL %q: %w\", proxyAddr, err)\n\t\t}\n\t\tproxyFunc = http.ProxyURL(proxyURL)\n\t} else if os.Getenv(\"HTTP_PROXY\") != \"\" || os.Getenv(\"HTTPS_PROXY\") != \"\" {\n\t\tproxyFunc = http.ProxyFromEnvironment\n\t}\n\n\tif proxyFunc == nil {\n\t\treturn nil\n\t}\n\n\ttransport := &http.Transport{Proxy: proxyFunc}\n\tsession.Client = &http.Client{\n\t\tTimeout:   sendTimeout,\n\t\tTransport: transport,\n\t}\n\n\tif session.Dialer != nil {\n\t\tdialerCopy := *session.Dialer","sourceCodeStart":758,"sourceCodeEnd":794,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/channels/discord/discord.go#L758-L794","documentation":"applyDiscordProxy failed to url.Parse the configured discord proxy address (%q prints the exact string); the parse error is wrapped with %w. It fires at channel construction, so the Discord channel never starts. Almost always the address lacks a scheme — url.Parse requires one for a usable proxy URL.","triggerScenarios":"Setting discord.proxy to 'host:port' (e.g. '127.0.0.1:7890') without an http:// or socks5:// scheme, stray whitespace/quotes, or a trailing newline from an env-sourced config value.","commonSituations":"Copying the proxy address from a GUI client that displays it without scheme, config templating that injects whitespace, switching between HTTP and SOCKS proxies.","solutions":["Add the scheme: http://127.0.0.1:7890, https://..., or socks5://127.0.0.1:7890","Trim whitespace/newlines from the config value","Alternatively unset discord.proxy and use HTTP_PROXY/HTTPS_PROXY env vars, which applyDiscordProxy also honors"],"exampleFix":"# before\nchannels:\n  discord:\n    proxy: \"127.0.0.1:7890\"\n\n# after\nchannels:\n  discord:\n    proxy: \"socks5://127.0.0.1:7890\"","handlingStrategy":"validation","validationCode":"func validProxyURL(addr string) error {\n    if addr == \"\" {\n        return nil\n    }\n    u, err := url.Parse(strings.TrimSpace(addr))\n    if err != nil {\n        return fmt.Errorf(\"invalid discord proxy URL %q: %w\", addr, err)\n    }\n    if u.Scheme == \"\" || u.Host == \"\" {\n        return fmt.Errorf(\"proxy URL %q needs a scheme (http/https/socks5) and host\", addr)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write proxy URLs with an explicit scheme: http://, https://, or socks5://","Validate proxy config at load time, not at channel construction","Trim whitespace/newlines from env-sourced config values"],"tags":["discord","proxy","config","url","validation"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}