{"record":{"id":"ab0b62ca1273bb32","repo":"kubernetes/kops","slug":"host-is-empty","errorCode":null,"errorMessage":"host is empty","messagePattern":"host is empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/dump/dumper.go","lineNumber":682,"sourceCode":"var _ sshClientFactory = &sshClientFactoryImplementation{}\n\n// HasBastion implements sshClientFactory::HasBastion\nfunc (f *sshClientFactoryImplementation) HasBastion() bool {\n\treturn f.bastion != \"\"\n}\n\n// Dial implements sshClientFactory::Dial\nfunc (f *sshClientFactoryImplementation) Dial(ctx context.Context, host string, useBastion bool) (sshClient, error) {\n\taddr := host\n\tif useBastion {\n\t\tif f.bastion == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"bastion is not set, but useBastion is true\")\n\t\t}\n\t\taddr = f.bastion\n\t}\n\n\tif addr == \"\" {\n\t\treturn nil, fmt.Errorf(\"host is empty\")\n\t}\n\taddr = net.JoinHostPort(addr, \"22\")\n\td := net.Dialer{\n\t\tTimeout: 5 * time.Second,\n\t}\n\tconn, err := d.DialContext(ctx, \"tcp\", addr)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error dialing tcp %s: %w\", addr, err)\n\t}\n\n\t// We have a TCP connection; we will force-close it to support context cancellation\n\n\tvar client *ssh.Client\n\tfinished := make(chan error)\n\tgo func() {\n\t\tc, chans, reqs, err := ssh.NewClientConn(conn, addr, f.sshConfig)\n\t\tif err == nil {\n\t\t\tclient = ssh.NewClient(c, chans, reqs)","sourceCodeStart":664,"sourceCodeEnd":700,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/dump/dumper.go#L664-L700","documentation":"Dial validates that the address it will connect to is non-empty after optional bastion substitution. If host is \"\" and useBastion is false (or the bastion substitution was skipped), there is nothing to dial, so the library returns this error rather than attempting a meaningless TCP connection. It signals that the caller supplied an empty target address.","triggerScenarios":"Calling Dial(ctx, \"\", false) — i.e. an empty host string — or Dial(ctx, \"\", true) would have hit the bastion check first; this error fires when addr remains \"\" after the useBastion block, meaning host was \"\" and useBastion was false.","commonSituations":"Instance list built from kops cluster state where a node has no external/internal IP recorded (e.g. instance not yet registered, terminated node, or API returning empty address fields); passing an unset string variable for host.","solutions":["Filter or skip entries with empty host/IP before calling Dial","Re-fetch instance addresses from the cloud provider (the instance may have no recorded IP yet) and retry","Log the offending record and exclude it from the dump target list"],"exampleFix":"// before\nclient, err := factory.Dial(ctx, node.Status.Addresses[\"internalIP\"], false)\n\n// after\naddr := node.Status.Addresses[\"internalIP\"]\nif addr == \"\" {\n\tklog.Warningf(\"skipping node %s: no address\", node.Name)\n\treturn nil\n}\nclient, err := factory.Dial(ctx, addr, false)","handlingStrategy":"validation","validationCode":"if host == \"\" {\n\treturn fmt.Errorf(\"refusing to dial: empty host address\")\n}\nclient, err := factory.Dial(ctx, host, false)","typeGuard":"func hasAddress(host string) bool { return strings.TrimSpace(host) != \"\" }","tryCatchPattern":"client, err := factory.Dial(ctx, host, false)\nif err != nil {\n\tif strings.Contains(err.Error(), \"host is empty\") {\n\t\tklog.Warningf(\"skipping target with empty address\")\n\t\treturn nil\n\t}\n\treturn err\n}","preventionTips":["Filter instance lists for non-empty addresses before dumping","Validate cloud-provider instance data freshness (terminated nodes often have no IP)","Fail fast on empty address fields when building dump targets"],"tags":["ssh","validation","empty-value"],"backgroundTag":"empty-host-address","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}