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
- Free up ephemeral ports / reduce concurrent listeners and retry.
- Loosen the sandbox/seccomp profile to allow localhost TCP bind.
- Run pkgsite manually on a fixed port and open the URL yourself.
- 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
- Limit concurrent listeners in CI to avoid port exhaustion.
- Allow localhost TCP bind in sandbox profiles.
- Keep pkgsite installed if you rely on `go doc -http`.
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
- internal error: failed to construct url: %v
- stopped after 10 redirects
- file URL specifies non-local host
- tls: server sent an unnecessary HelloRetryRequest key_share
- tls: server sent two HelloRetryRequest messages
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/41309b589eb4fcfe.
Report an issue: GitHub.