XTLS/Xray-core · error
invalid URL:
Error message
invalid URL:
What it means
Thrown by FetchHTTPContent after utils.SplitHTTPUnixURL splits the target into an HTTP URL and an optional socket path. The remaining HTTP part is passed to url.Parse, which rejects strings containing control characters or otherwise malformed URL syntax. This is the entry point for Xray's remote config fetching, supporting plain http(s) plus Unix/abstract-socket targets.
Source
Thrown at main/confloader/external/external.go:59
return
}
// FetchHTTPContent issues an HTTP GET against either a regular HTTP(S) URL
// or a Unix socket HTTP endpoint.
//
// http(s)://host/api regular HTTP(S)
// /path/to/socket.sock[:/api] filesystem socket
// @abstract[:/api] abstract socket (Linux/Android)
// @@padded[:/api] padded abstract socket (HAProxy compat)
//
// When the ":/" separator is omitted on a socket target, the request is
// made to "/".
func FetchHTTPContent(target string) ([]byte, error) {
httpURL, socketPath := utils.SplitHTTPUnixURL(target)
parsedTarget, err := url.Parse(httpURL)
if err != nil {
return nil, errors.New("invalid URL: ", target).Base(err)
}
client := &http.Client{
Timeout: 30 * time.Second,
}
if socketPath != "" {
dialAddr := utils.ResolveSocketPath(socketPath)
client.Transport = &http.Transport{
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
var d net.Dialer
return d.DialContext(ctx, "unix", dialAddr)
},
}
}
resp, err := client.Do(&http.Request{
Method: "GET",View on GitHub (pinned to 7d214f8b09)
Solutions
- Inspect the exact target string passed on the command line or in code; strip leading/trailing whitespace, newlines and carriage returns
- Ensure the URL has a valid scheme: http:// or https:// for network, or /path, @name, @@name forms for sockets
- URL-encode any spaces or special characters in the path/query portion of the target
- If the target is a local file, remove any http-like prefix and pass the filesystem path instead
Example fix
// before
content, err := external.FetchHTTPContent("http://example.com/conf x.json\n")
// after
target := strings.TrimSpace("http://example.com/conf%20x.json")
content, err := external.FetchHTTPContent(target) Defensive patterns
Strategy: validation
Validate before calling
import ("net/url"; "strings")
func validFetchTarget(target string) bool {
t := strings.TrimSpace(target)
if t == "" { return false }
httpPart, _ := utils.SplitHTTPUnixURL(t) // or replicate the split
_, err := url.Parse(httpPart)
return err == nil
} Try / catch
if content, err := external.FetchHTTPContent(t); err != nil {
if strings.HasPrefix(err.Error(), "invalid URL") { fixTarget(t); continue }
return err
} Prevention
- Trim whitespace/newlines from any URL pulled from env vars or flags
- Centralize config-URL construction in one helper that validates with url.Parse
- Prefer static, well-formed URLs; avoid assembling them from untrusted fragments
When it happens
Trigger: Calling confloader.LoadConfig with a target like "http(s)://host/api", "/path/to/socket.sock:/api", "@abstract:/api" or "@@padded:/api" where the URL portion contains control characters (e.g. raw newline/tab), an unsupported scheme remnant, or other input url.Parse refuses.
Common situations: Typos in the -config flag (missing scheme, stray whitespace or CR from copy-pasting a URL, unescaped spaces), or a Windows-style path accidentally passed as an http URL; also malformed socket-target syntax that SplitHTTPUnixURL does not normalize.
Related errors
- invalid scheme + u.Scheme
- invalid host + host
- invalid token + token
- invalid id + id
- empty HTTP header value: + key
AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15).
Data as JSON: /api/errors/11b5c0c027c8d70a.
Report an issue: GitHub.