github/copilot-sdk · error

Invalid URIConnection format

Error message

Invalid URIConnection format: %s

What it means

parseCLIURL in go/client.go parses the URIConnection URL passed to NewClient. When the URL looks like a bracketed host:port ([v6]:port) it validates that the host is a valid IPv6 address; if netip.ParseAddr fails or the address is not IPv6, it panics with this message. The library only accepts IPv6 literal hosts in the bracketed form, so any other host form here is rejected.

Solutions

  1. Use an IPv6 literal inside brackets, e.g. "http://[::1]:3000"
  2. Use the plain host:port form without brackets for IPv4/hostname, e.g. "http://localhost:3000"
  3. Pass only a port (e.g. ":3000" or the port string) to default to localhost
  4. Log/print the exact URL string before NewClient to spot bracket or colon mistakes

Example fix

// before
client := NewClient("http://[myhost]:3000")
// after
client := NewClient("http://localhost:3000") // or "http://[::1]:3000" for IPv6
Defensive patterns

Strategy: validation

Validate before calling

func validCLIURL(u string) bool {
	host, port, err := net.SplitHostPort(u)
	if err != nil {
		return false
	}
	if strings.HasPrefix(u, "[") {
		addr, err := netip.ParseAddr(host)
		return err == nil && addr.Is6()
	}
	_, err = strconv.Atoi(port)
	return err == nil
}

Type guard

func isIPv6Literal(host string) bool {
	addr, err := netip.ParseAddr(host)
	return err == nil && addr.Is6()
}

Prevention

When it happens

Trigger: Calling NewClient with a CLI URL like "http://[hostname]:3000" or "[::1:notanumber]" where SplitHostPort succeeds (bracketed form) but the host inside brackets is not a valid IPv6 literal (e.g. a DNS name, IPv4, or malformed address).

Common situations: Developers put a hostname or IPv4 address inside brackets instead of an IPv6 literal, or hand-build the URL string with typos (missing/extra colons), or an environment variable containing the server URL was set to a non-IPv6 bracketed value.

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/fad8ada5ae86f1a7. Report an issue: GitHub.

Appendix: source

Thrown at go/client.go:421

// 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
	} else {
		portStr = cleanURL
	}

View on GitHub (pinned to cd8cf15dc3)