{"record":{"id":"41309b589eb4fcfe","repo":"golang/go","slug":"failed-to-find-port-for-documentation-server-v","errorCode":null,"errorMessage":"failed to find port for documentation server: %v","messagePattern":"failed to find port for documentation server: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cmd/go/internal/doc/pkgsite.go","lineNumber":107,"sourceCode":"\tp.Internal.ExeName = p.DefaultExecName()\n\tload.CheckPackageErrors([]*load.Package{p})\n\n\ta := b.LinkAction(loader, work.ModeBuild, work.ModeBuild, p)\n\ta.CacheExecutable = true\n\tb.Do(ctx, a)\n\n\t// Both paths return an executable in GOCACHE: CachedExecutable is set on\n\t// fresh builds, while BuiltTarget is set on cache hits.\n\tif cached := a.CachedExecutable(); cached != \"\" {\n\t\treturn cached\n\t}\n\treturn a.BuiltTarget()\n}\n\nfunc doPkgsite(ctx context.Context, urlPath, fragment string) error {\n\tport, err := pickUnusedPort()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to find port for documentation server: %v\", err)\n\t}\n\taddr := fmt.Sprintf(\"localhost:%d\", port)\n\tpath, err := url.JoinPath(\"http://\"+addr, urlPath)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"internal error: failed to construct url: %v\", err)\n\t}\n\tif fragment != \"\" {\n\t\tpath += \"#\" + fragment\n\t}\n\n\tif file := os.Getenv(\"TEST_GODOC_URL_FILE\"); file != \"\" {\n\t\treturn os.WriteFile(file, []byte(path+\"\\n\"), 0666)\n\t}\n\n\t// Turn off the default signal handler for SIGINT (and SIGQUIT on Unix)\n\t// and instead wait for the child process to handle the signal and\n\t// exit before exiting ourselves.\n\tbase.StartSigHandlers()","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/cmd/go/internal/doc/pkgsite.go#L89-L125","documentation":"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.","triggerScenarios":"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.","commonSituations":"CI with many concurrent listeners; containers with constrained net namespaces; security policy denying bind; transient port exhaustion under load.","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."],"exampleFix":"# before\n$ go doc -http\n# -> failed to find port for documentation server: ...\n\n# after: run pkgsite yourself on a fixed port\n$ pkgsite -http=localhost:6060\n# or use the CLI form\n$ go doc fmt","handlingStrategy":"fallback","validationCode":"// probe a free port yourself; if that fails, fall back to CLI doc\nl, err := net.Listen(\"tcp\", \"localhost:0\")\nif err != nil { return ErrNoPortForDocs }\ndefer l.Close()\nport := l.Addr().(*net.TCPAddr).Port","typeGuard":null,"tryCatchPattern":"if err := doPkgsite(ctx, urlPath, fragment); err != nil {\n    if strings.Contains(err.Error(), \"failed to find port\") {\n        // fall back to non-HTTP doc output\n        return runCLIDoc(ctx, urlPath)\n    }\n}","preventionTips":["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`."],"tags":["doc","pkgsite","network","port"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}