{"record":{"id":"8a96afb92967cc5c","repo":"kubernetes/kops","slug":"arn-q-contains-too-few-slashes","errorCode":null,"errorMessage":"arn %q contains too few slashes","messagePattern":"arn %q contains too few slashes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/bootstrap/awsbootstrap/verifier.go","lineNumber":280,"sourceCode":"\t\treturn nil, fmt.Errorf(\"arn %q contains unexpected number of colons\", arn)\n\t}\n\tif parts[0] != \"arn\" {\n\t\treturn nil, fmt.Errorf(\"arn %q doesn't start with \\\"arn:\\\"\", arn)\n\t}\n\tif parts[1] != a.partition {\n\t\treturn nil, fmt.Errorf(\"arn %q not in partion %q\", arn, a.partition)\n\t}\n\tif parts[2] != \"iam\" && parts[2] != \"sts\" {\n\t\treturn nil, fmt.Errorf(\"arn %q has unrecognized service\", arn)\n\t}\n\t// parts[3] is region\n\t// parts[4] is account\n\tresource := strings.Split(parts[5], \"/\")\n\tif resource[0] != \"assumed-role\" {\n\t\treturn nil, fmt.Errorf(\"arn %q has unrecognized type\", arn)\n\t}\n\tif len(resource) < 3 {\n\t\treturn nil, fmt.Errorf(\"arn %q contains too few slashes\", arn)\n\t}\n\tfound := false\n\tfor _, role := range a.opt.NodesRoles {\n\t\tif resource[1] == role {\n\t\t\tfound = true\n\t\t\tbreak\n\t\t}\n\t}\n\tif !found {\n\t\treturn nil, fmt.Errorf(\"arn %q does not contain acceptable node role\", arn)\n\t}\n\n\tinstanceID := resource[2]\n\tinstances, err := a.ec2.DescribeInstances(ctx, &ec2.DescribeInstancesInput{\n\t\tInstanceIds: []string{instanceID},\n\t})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"describing instance for arn %q\", arn)","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/bootstrap/awsbootstrap/verifier.go#L262-L298","documentation":"After confirming the ARN resource starts with \"assumed-role\", kOps splits it and requires at least three slash-separated segments: \"assumed-role\", the role name, and the session name (which kOps uses as the EC2 instance ID). This error is thrown when an assumed-role ARN lacks the session/instance-ID segment, so the instance cannot be identified.","triggerScenarios":"verifyCallerIdentity receives an ARN like arn:aws:sts::123:assumed-role/nodes.cluster (only two resource segments, no trailing \"/<session>\") — i.e. an AssumeRole session was created without a meaningful RoleSessionName or the session name itself contains no instance ID.","commonSituations":"Custom code calling sts:AssumeRole on the node role without setting RoleSessionName to the instance ID; older kOps nodeup versions or third-party tools assuming the role with a non-instance-ID session name; hand-crafted tokens used against the challenge endpoint.","solutions":["Ensure nodeup obtains credentials via the instance metadata service (IMDS) so the session name is the instance ID, rather than calling AssumeRole itself.","If assuming the node role manually for testing, set RoleSessionName to the EC2 instance ID: aws sts assume-role --role-arn ... --role-session-name i-0abc123.","Check nodeup/kOps version consistency between control plane and nodes; upgrade outdated nodeup.","Confirm nothing in the environment proxies or rewrites bootstrap requests with different credentials."],"exampleFix":"// before (custom token generator)\nsts.AssumeRole(&sts.AssumeRoleInput{RoleArn: r, RoleSessionName: aws.String(\"tmp\")})\n// after\nsts.AssumeRole(&sts.AssumeRoleInput{RoleArn: r, RoleSessionName: aws.String(instanceID)})","handlingStrategy":"validation","validationCode":"res := strings.Split(strings.Split(arn, \":\")[5], \"/\")\nif len(res) < 3 {\n    return fmt.Errorf(\"assumed-role ARN %q lacks session/instance-id segment; set RoleSessionName to the instance ID\", arn)\n}","typeGuard":"func arnHasInstanceID(arn string) (string, bool) {\n\tres := strings.Split(strings.Split(arn, \":\")[5], \"/\")\n\tif len(res) < 3 || !strings.HasPrefix(res[2], \"i-\") {\n\t\treturn \"\", false\n\t}\n\treturn res[2], true\n}","tryCatchPattern":null,"preventionTips":["Always obtain node credentials from IMDS, not from manual AssumeRole calls.","If calling AssumeRole in tests, set --role-session-name to the EC2 instance ID.","Keep nodeup and control-plane versions in sync."],"tags":["aws","sts","bootstrap","arn"],"backgroundTag":"arn-malformed-assumed-role","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"}