{"record":{"id":"2c98276012ed80c4","repo":"lima-vm/lima","slug":"failed-to-find-a-free-port-try-setting-ssh-local","errorCode":null,"errorMessage":"failed to find a free port, try setting `ssh.localPort` manually: %w","messagePattern":"failed to find a free port, try setting `ssh\\.localPort` manually: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/hostagent/hostagent.go","lineNumber":335,"sourceCode":"\t}\n\tfileName := filepath.Join(instDir, filenames.SSHConfig)\n\treturn os.WriteFile(fileName, b.Bytes(), 0o600)\n}\n\nfunc determineSSHLocalPort(confLocalPort int, instName, limaVersion string) (int, error) {\n\tif confLocalPort > 0 {\n\t\treturn confLocalPort, nil\n\t}\n\tif confLocalPort < 0 {\n\t\treturn 0, fmt.Errorf(\"invalid ssh local port %d\", confLocalPort)\n\t}\n\tif versionutil.LessThan(limaVersion, \"2.0.0\") && instName == \"default\" {\n\t\t// use hard-coded value for \"default\" instance, for backward compatibility\n\t\treturn 60022, nil\n\t}\n\tsshLocalPort, err := freeport.TCP()\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"failed to find a free port, try setting `ssh.localPort` manually: %w\", err)\n\t}\n\treturn sshLocalPort, nil\n}\n\nfunc (a *HostAgent) emitEvent(_ context.Context, ev events.Event) {\n\ta.eventEncMu.Lock()\n\tdefer a.eventEncMu.Unlock()\n\n\ta.statusMu.Lock()\n\ta.currentStatus = ev.Status\n\ta.statusMu.Unlock()\n\n\tif ev.Time.IsZero() {\n\t\tev.Time = time.Now()\n\t}\n\tif err := a.eventEnc.Encode(ev); err != nil {\n\t\tlogrus.WithField(\"event\", ev).WithError(err).Error(\"failed to emit an event\")\n\t}","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/lima-vm/lima/blob/dd909d0973cd84fa35f9e1693181b4585ea616c1/pkg/hostagent/hostagent.go#L317-L353","documentation":"When ssh.localPort is 0 (or unset for non-legacy instances), Lima asks freeport.TCP() for an available local TCP port. If no free port can be found, this error is returned, advising the user to pin ssh.localPort manually.","triggerScenarios":"limactl start on an instance where the SSH local port must be auto-selected and freeport.TCP fails — typically because no ports are available in its scan range.","commonSituations":"Exhausted ephemeral port range from many open connections/VMs; firewall or security software blocking bind probes; restrictive container/network namespaces limiting available ports; running thousands of Lima instances concurrently.","solutions":["Set an explicit port in the config: ssh.localPort: <free-port> (e.g. 60022), ensuring nothing else binds it","Free up ports: close idle VMs/connections or widen the local ephemeral port range (net.ipv4.ip_local_port_range on Linux)","Check for security software or network policies intercepting local binds","Retry after transient exhaustion — free port availability often recovers once connections close"],"exampleFix":"// before (lima.yaml)\nssh: {}\n// after\nssh:\n  localPort: 60022","handlingStrategy":"validation","validationCode":"// confirm a usable local port exists before starting\nl, err := net.Listen(\"tcp\", \"127.0.0.1:0\")\nif err != nil {\n\treturn fmt.Errorf(\"no local ports available: %w\", err)\n}\nl.Close()","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"failed to find a free port\") {\n\t// pin a known-free port and retry once\n\tinst.Config.SSH.LocalPort = limayaml.PointInt(60022)\n\treturn startInstance(ctx, inst)\n}","preventionTips":["Set an explicit ssh.localPort when running many instances or in restricted sandboxes","Monitor ephemeral port usage; widen net.ipv4.ip_local_port_range if often exhausted","Avoid running security software that intercepts local bind attempts","Close idle Lima instances to release reserved ports"],"tags":["ssh","port","network","port-exhaustion"],"backgroundTag":"no-free-port","analyzedSha":"dd909d0973cd84fa35f9e1693181b4585ea616c1","analyzedAt":"2026-09-01T14:24:59.842Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}