{"record":{"id":"1c54c9a3d47fd8a7","repo":"kubernetes/kops","slug":"hostname-was-empty","errorCode":null,"errorMessage":"hostname was empty","messagePattern":"hostname was empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/toolbox_enroll.go","lineNumber":425,"sourceCode":"\t}\n\tif err := session.Run(command); err != nil {\n\t\treturn output, fmt.Errorf(\"error running command %q: %w\", command, err)\n\t}\n\treturn output, nil\n}\n\n// getHostname gets the hostname of the SSH target.\n// This is used as the node name when registering the node.\nfunc (s *SSHHost) getHostname(ctx context.Context) (string, error) {\n\toutput, err := s.runCommand(ctx, \"hostname\", ExecOptions{Echo: true})\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to get hostname: %w\", err)\n\t}\n\n\thostname := output.Stdout.String()\n\thostname = strings.TrimSpace(hostname)\n\tif len(hostname) == 0 {\n\t\treturn \"\", fmt.Errorf(\"hostname was empty\")\n\t}\n\treturn hostname, nil\n}\n\ntype BootstrapData struct {\n\t// NodeupScript is a script that can be used to bootstrap the node.\n\tNodeupScript []byte\n\t// NodeupConfig is structured configuration, provided by kops-controller (for example).\n\tNodeupConfig *nodeup.Config\n\t// NodeupScriptAdditionalFiles are additional files that are needed by the nodeup script.\n\tNodeupScriptAdditionalFiles map[string][]byte\n}\n\n// ConfigBuilder builds bootstrap configuration for a node.\ntype ConfigBuilder struct {\n\t// ClusterName is the name of the cluster to build.\n\t// Required (unless Cluster is set).\n\tClusterName string","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/commands/toolbox_enroll.go#L407-L443","documentation":"After running `hostname` over SSH, getHostname trims the output and fails if it is empty. A node cannot be registered without a name, so kOps returns this explicit validation error rather than using an empty node name.","triggerScenarios":"The remote `hostname` command succeeds but writes nothing to stdout — e.g. a shell profile suppresses output, a non-standard shell/alias overrides `hostname`, or the SSH server behaves abnormally.","commonSituations":"Custom shell rc files printing to stderr but the command output being misdirected; restricted shells (rbash) intercepting commands; running `hostname` against an appliance/non-standard SSH target.","solutions":["Run `hostname` manually over SSH as the same user and confirm non-empty output","Check the target's shell rc/profile for aliases or stty/echo tricks affecting output","Set the system hostname on the node (hostnamectl set-hostname <name>) and retry","Use a fallback explicit node name if the tooling allows specifying it"],"exampleFix":"// before\n// relies on remote `hostname` output\n// after\n$ ssh user@host 'hostname; echo EXIT=$?'  # verify non-empty output and exit 0\n$ sudo hostnamectl set-hostname node-1","handlingStrategy":"validation","validationCode":"out, _ := exec.Command(\"ssh\", user+\"@\"+host, \"hostname\").Output()\nif len(strings.TrimSpace(string(out))) == 0 {\n    return errors.New(\"remote hostname is empty; set it with hostnamectl\")\n}","typeGuard":"func hasValidRemoteHostname(out *CommandOutput) bool {\n    return out != nil && strings.TrimSpace(out.Stdout.String()) != \"\"\n}","tryCatchPattern":null,"preventionTips":["Set a proper hostname on every node before enroll","Keep node shell profiles free of output-altering commands","Test `ssh user@host hostname` returns a non-empty line"],"tags":["ssh","validation","hostname"],"backgroundTag":"empty-command-output","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"}