{"record":{"id":"9638e735932eeb4a","repo":"kubernetes/kops","slug":"invalid-etcdclusterspec-expected-two-tokens-q","errorCode":null,"errorMessage":"invalid EtcdClusterSpec (expected two tokens): %q","messagePattern":"invalid EtcdClusterSpec \\(expected two tokens\\): %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/etcd/cluster_spec.go","lineNumber":46,"sourceCode":"\t// NodeName is my nodename in the cluster\n\tNodeName string `json:\"nodeName,omitempty\"`\n\t// NodeNames is a collection of node members in the cluster\n\tNodeNames []string `json:\"nodeNames,omitempty\"`\n}\n\n// String returns a string representation of the EtcdClusterSpec\nfunc (e *EtcdClusterSpec) String() string {\n\treturn DebugString(e)\n}\n\n// ParseEtcdClusterSpec parses a tag on a volume that encodes an etcd cluster role\n// The format is \"<myname>/<allnames>\", e.g. \"node1/node1,node2,node3\"\nfunc ParseEtcdClusterSpec(clusterKey, v string) (*EtcdClusterSpec, error) {\n\tv = strings.TrimSpace(v)\n\n\ttokens := strings.Split(v, \"/\")\n\tif len(tokens) != 2 {\n\t\treturn nil, fmt.Errorf(\"invalid EtcdClusterSpec (expected two tokens): %q\", v)\n\t}\n\n\tnodeName := tokens[0]\n\tnodeNames := strings.Split(tokens[1], \",\")\n\n\tfound := false\n\tfor _, s := range nodeNames {\n\t\tif s == nodeName {\n\t\t\tfound = true\n\t\t}\n\t}\n\tif !found {\n\t\treturn nil, fmt.Errorf(\"invalid EtcdClusterSpec (member not found in all nodes): %q\", v)\n\t}\n\n\tc := &EtcdClusterSpec{\n\t\tClusterKey: clusterKey,\n\t\tNodeName:   nodeName,","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/etcd/cluster_spec.go#L28-L64","documentation":"ParseEtcdClusterSpec parses an etcd cluster role tag stored on an etcd volume, expected in the form \"<myname>/<allnames>\" (e.g. \"node1/node1,node2,node3\"). This error is thrown when the trimmed value does not split into exactly two '/'-separated tokens. It means the volume tag content is malformed and cannot encode a valid cluster membership spec.","triggerScenarios":"findEtcdStatus reads the cluster-spec tag from an etcd volume and passes it to ParseEtcdClusterSpec; the string contains zero '/' characters (e.g. \"node1\"), or more than one '/' (e.g. \"node1/node1,node2/extra\"), or an empty string, so strings.Split returns a slice whose length != 2.","commonSituations":"Volumes created by an older kops version with a different tag format; a volume tag manually edited or truncated; passing a hostname or FQDN containing '/' by mistake; an empty/uninitialized tag value on a recreated volume.","solutions":["Print the offending value (quoted in the error) and correct the volume tag to the exact \"<myname>/<allnames>\" format, e.g. \"node1/node1,node2,node3\".","Ensure no extra '/' characters appear anywhere in the value; node names must not contain slashes.","If volumes were created by an incompatible kops version, either recreate the etcd volumes with the current `kops` version or use `kops toolbox` tooling to migrate the tags.","Verify the instance/volume was fully initialized — an empty tag means the etcd volume setup did not complete; rerun cluster creation/upgrade."],"exampleFix":"// before: malformed tag value on the etcd volume\nv := \"node1\"\n// after: correct two-token format \"<myname>/<allnames>\"\nv := \"node1/node1,node2,node3\"","handlingStrategy":"validation","validationCode":"// validate an etcd cluster-spec tag before calling ParseEtcdClusterSpec\nfunc validEtcdClusterSpecShape(v string) bool {\n    v = strings.TrimSpace(v)\n    if v == \"\" {\n        return false\n    }\n    parts := strings.Split(v, \"/\")\n    if len(parts) != 2 || parts[0] == \"\" || parts[1] == \"\" {\n        return false\n    }\n    for _, n := range strings.Split(parts[1], \",\") {\n        if strings.TrimSpace(n) == \"\" {\n            return false\n        }\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write volume tags in \"<myname>/<allnames>\" format with exactly one '/'.","Never include '/' inside node names.","Verify tags exist after volume provisioning completes before reading them.","Re-create or re-tag volumes created by older/incompatible kops versions."],"tags":["etcd","parsing","kops","config"],"backgroundTag":"etcd-cluster-spec-parse-error","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"}