golang/go · error

failed to find port for documentation server: %v

Error message

failed to find port for documentation server: %v

What it means

Returned by doPkgsite when pickUnusedPort() fails to obtain a free TCP port for the local pkgsite documentation server. Without a port the HTTP server cannot bind, so `go doc -http` (or the pkgsite fallback) cannot start.

Source

Thrown at src/cmd/go/internal/doc/pkgsite.go:107

	p.Internal.ExeName = p.DefaultExecName()
	load.CheckPackageErrors([]*load.Package{p})

	a := b.LinkAction(loader, work.ModeBuild, work.ModeBuild, p)
	a.CacheExecutable = true
	b.Do(ctx, a)

	// Both paths return an executable in GOCACHE: CachedExecutable is set on
	// fresh builds, while BuiltTarget is set on cache hits.
	if cached := a.CachedExecutable(); cached != "" {
		return cached
	}
	return a.BuiltTarget()
}

func doPkgsite(ctx context.Context, urlPath, fragment string) error {
	port, err := pickUnusedPort()
	if err != nil {
		return fmt.Errorf("failed to find port for documentation server: %v", err)
	}
	addr := fmt.Sprintf("localhost:%d", port)
	path, err := url.JoinPath("http://"+addr, urlPath)
	if err != nil {
		return fmt.Errorf("internal error: failed to construct url: %v", err)
	}
	if fragment != "" {
		path += "#" + fragment
	}

	if file := os.Getenv("TEST_GODOC_URL_FILE"); file != "" {
		return os.WriteFile(file, []byte(path+"\n"), 0666)
	}

	// Turn off the default signal handler for SIGINT (and SIGQUIT on Unix)
	// and instead wait for the child process to handle the signal and
	// exit before exiting ourselves.
	base.StartSigHandlers()

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Free up ephemeral ports / reduce concurrent listeners and retry.
  2. Loosen the sandbox/seccomp profile to allow localhost TCP bind.
  3. Run pkgsite manually on a fixed port and open the URL yourself.
  4. Fall back to CLI `go doc <pkg>` instead of the HTTP server.

Example fix

# before
$ go doc -http
# -> failed to find port for documentation server: ...

# after: run pkgsite yourself on a fixed port
$ pkgsite -http=localhost:6060
# or use the CLI form
$ go doc fmt
Defensive patterns

Strategy: fallback

Validate before calling

// probe a free port yourself; if that fails, fall back to CLI doc
l, err := net.Listen("tcp", "localhost:0")
if err != nil { return ErrNoPortForDocs }
defer l.Close()
port := l.Addr().(*net.TCPAddr).Port

Try / catch

if err := doPkgsite(ctx, urlPath, fragment); err != nil {
    if strings.Contains(err.Error(), "failed to find port") {
        // fall back to non-HTTP doc output
        return runCLIDoc(ctx, urlPath)
    }
}

Prevention

When it happens

Trigger: Calling doPkgsite on a host where no ephemeral port can be allocated — port exhaustion, a sandbox blocking socket binding, or a restrictive seccomp/AppArmor profile.

Common situations: CI with many concurrent listeners; containers with constrained net namespaces; security policy denying bind; transient port exhaustion under load.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/41309b589eb4fcfe. Report an issue: GitHub.