kubernetes/kops · error

failed to find lifecycle hook

Error message

failed to find lifecycle hook %q: %w

What it means

completeWarmingLifecycleAction describes the lifecycle hook named 'kops-warmpool' on the ASG '<instancegroup>.<clustername>'. If the DescribeLifecycleHooks API call itself errors (as opposed to returning zero hooks), nodeup wraps the AWS error with this message and the Run() call fails.

Solutions

  1. Grant the node instance role autoscaling:DescribeLifecycleHooks (scoped to the cluster ASGs if possible).
  2. Verify the ASG name <ig>.<cluster> exists in the node's region (aws autoscaling describe-auto-scaling-groups).
  3. Check the wrapped AWS error code: AuthorizationError -> permissions, ValidationError -> ASG name, Throttling -> backoff/retry.
  4. Ensure nodeup and cluster spec versions agree so hook/ASG naming conventions match.

Example fix

// before
// (no autoscaling:DescribeLifecycleHooks on node role)
// after
{"Effect":"Allow","Action":"autoscaling:DescribeLifecycleHooks","Resource":"*"}
Defensive patterns

Strategy: try-catch

Validate before calling

aws iam simulate-principal-policy --policy-source-arn <nodeRoleArn> --action-names autoscaling:DescribeLifecycleHooks --resource-arns '*'

Try / catch

hooks, err := cloud.DescribeLifecycleHooks(ctx, input)
if err != nil {
    var ae smithy.APIError
    if errors.As(err, &ae) {
        switch ae.ErrorCode() {
        case "AccessDenied": // fix IAM
        case "ValidationError": // wrong ASG name
        case "ThrottlingException": // backoff & retry
        }
    }
    return fmt.Errorf("failed to find lifecycle hook %q: %w", hookName, err)
}

Prevention

When it happens

Trigger: cloud.DescribeLifecycleHooks fails: IAM permission denied for autoscaling:DescribeLifecycleHooks, nonexistent/wrong ASG name, AWS API throttling, or regional/network failure.

Common situations: Node IAM role missing DescribeLifecycleHooks permission; instance group renamed so the ASG lookup name no longer matches; ASG is in a different region than the node's configured region; SDK throttling during large scale-ups.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/dfee51390abf07c7. Report an issue: GitHub.

Appendix: source

Thrown at upup/pkg/fi/nodeup/command.go:440

		return "", fmt.Errorf("failed to get instance metadata type: %w", err)
	}
	defer result.Content.Close()
	instanceTypeName, err := io.ReadAll(result.Content)
	if err != nil {
		return "", fmt.Errorf("failed to read instance metadata response: %w", err)
	}
	return string(instanceTypeName), err
}

func completeWarmingLifecycleAction(ctx context.Context, cloud *awsup.Cloud, modelContext *model.NodeupModelContext) error {
	asgName := modelContext.BootConfig.InstanceGroupName + "." + modelContext.NodeupConfig.ClusterName
	hookName := "kops-warmpool"
	hooks, err := cloud.DescribeLifecycleHooks(ctx, &autoscaling.DescribeLifecycleHooksInput{
		AutoScalingGroupName: &asgName,
		LifecycleHookNames:   []string{hookName},
	})
	if err != nil {
		return fmt.Errorf("failed to find lifecycle hook %q: %w", hookName, err)
	}

	if len(hooks.LifecycleHooks) > 0 {
		klog.Info("Found ASG lifecycle hook")
		_, err := cloud.CompleteLifecycleAction(ctx, &autoscaling.CompleteLifecycleActionInput{
			AutoScalingGroupName:  &asgName,
			InstanceId:            &modelContext.InstanceID,
			LifecycleHookName:     &hookName,
			LifecycleActionResult: new("CONTINUE"),
		})
		if err != nil {
			return fmt.Errorf("failed to complete lifecycle hook %q for %q: %v", hookName, modelContext.InstanceID, err)
		}
		klog.Info("Lifecycle action completed")
	} else {
		klog.Info("No ASG lifecycle hook found")
	}
	return nil

View on GitHub (pinned to 4c8573c808)