github/copilot-sdk · error

Invalid port in URIConnection

Error message

Invalid port in URIConnection: %s

What it means

parseCLIURL panics with "Invalid port in URIConnection: %s" when a bracketed IPv6 URIConnection URL cannot be split into host and port (net.SplitHostPort fails). This means the URL is malformed for the bracketed-IPv6 form the parser supports, e.g. missing the port or unbalanced brackets.

Solutions

  1. Use the full bracketed form with a port, e.g. "http://[::1]:4141".
  2. Validate the URL with net.SplitHostPort / url.Parse before constructing the client.
  3. If only the host is known, format it explicitly: fmt.Sprintf("http://[%s]:%d", host, port).

Example fix

// before
client := clientpkg.NewClient(&clientpkg.Options{
    Connection: clientpkg.URIConnection{URL: "[::1]"}, // no port
})
// after
client := clientpkg.NewClient(&clientpkg.Options{
    Connection: clientpkg.URIConnection{URL: "http://[::1]:4141"},
})
Defensive patterns

Strategy: validation

Validate before calling

if strings.HasPrefix(u, "[") {
    if _, _, err := net.SplitHostPort(u); err != nil {
        return fmt.Errorf("malformed bracketed IPv6 URL %q (need [host]:port)", u)
    }
}

Prevention

When it happens

Trigger: Passing URIConnection{URL: "[::1]"} or "[::1]:" or otherwise malformed bracketed IPv6 input to NewClient; parseCLIURL is invoked from NewClient when handling a URIConnection. Panic at go/client.go:417.

Common situations: Hand-assembling IPv6 URLs without brackets/port; templating a host into a URL string where the port segment is lost; IPv6 literals from environment config missing the [host]:port form.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/00c813d6d6e5854b. Report an issue: GitHub.

Appendix: source

Thrown at go/client.go:417

	}
	return append(filtered, key+"="+value)
}

// parseCLIURL parses a CLI URL into host and port components.
//
// Supports formats: "host:port", "[ipv6]:port", "http://host:port", "https://host:port", or just "port".
// Panics if the URL format is invalid or the port is out of range.
func parseCLIURL(url string) (string, int) {
	// Remove protocol if present
	cleanURL, _ := strings.CutPrefix(url, "https://")
	cleanURL, _ = strings.CutPrefix(cleanURL, "http://")

	// Use the standard parser only for the bracketed IPv6 form. Keep the
	// existing host:port parsing behavior for all other inputs.
	if strings.HasPrefix(cleanURL, "[") {
		host, portStr, err := net.SplitHostPort(cleanURL)
		if err != nil {
			panic(fmt.Sprintf("Invalid port in URIConnection: %s", url))
		}
		addr, err := netip.ParseAddr(host)
		if err != nil || !addr.Is6() {
			panic(fmt.Sprintf("Invalid URIConnection format: %s", url))
		}
		port, err := strconv.Atoi(portStr)
		if err != nil || port <= 0 || port > 65535 {
			panic(fmt.Sprintf("Invalid port in URIConnection: %s", url))
		}
		return host, port
	}

	// Parse host:port or port format
	var host string
	var portStr string
	if before, after, found := strings.Cut(cleanURL, ":"); found {
		host = before
		portStr = after

View on GitHub (pinned to cd8cf15dc3)