kubernetes/kops · error

duplicate resource found: %s.%s

Error message

duplicate resource found: %s.%s

What it means

GetResourcesByType groups rendered TerraformResource items by resource type, keyed by sanitized resource name. Terraform requires unique resource names within a type, so a second resource with the same type and name is rejected with this error during HCL2 finishing. This prevents emitting a Terraform config with duplicate resource blocks.

Source

Thrown at upup/pkg/fi/cloudup/terraformWriter/writer.go:245

	}

	return dataSourcesByType, nil
}

func (t *TerraformWriter) GetResourcesByType() (map[string]map[string]interface{}, error) {
	resourcesByType := make(map[string]map[string]interface{})

	for _, res := range t.resources {
		resources := resourcesByType[res.ResourceType]
		if resources == nil {
			resources = make(map[string]interface{})
			resourcesByType[res.ResourceType] = resources
		}

		tfName := sanitizeName(res.ResourceName)

		if resources[tfName] != nil {
			return nil, fmt.Errorf("duplicate resource found: %s.%s", res.ResourceType, tfName)
		}

		resources[tfName] = res.Item
	}

	return resourcesByType, nil
}

func (t *TerraformWriter) GetOutputs() (map[string]OutputValue, error) {
	values := map[string]OutputValue{}
	for _, v := range t.outputs {
		tfName := sanitizeName(v.Key)
		if _, found := values[tfName]; found {
			return nil, fmt.Errorf("duplicate variable found: %s", tfName)
		}
		deduped, err := dedupLiterals(v.ValueArray)
		if err != nil {
			return nil, err

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Rename the conflicting kOps objects (e.g. instance groups) so their Terraform names differ.
  2. Check the cluster spec for duplicated resources causing double registration.
  3. If names collide only after sanitization, shorten/adjust names to stay unique post-sanitize.
  4. Update kOps and/or file an upstream issue with the duplicate `<type>.<name>` from the message.

Example fix

// before
name: nodes.a
name: nodes.a   # duplicate -> aws_security_group.nodes-a
// after
name: nodes-a
name: nodes-b
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]bool{}
tfName := sanitizeName(res.ResourceName)
if seen[res.ResourceType+"."+tfName] {
    return fmt.Errorf("resource %s.%s would be registered twice", res.ResourceType, tfName)
}
seen[res.ResourceType+"."+tfName] = true

Try / catch

resByType, err := w.GetResourcesByType()
if err != nil {
    return fmt.Errorf("building terraform resources failed: %w", err)
}

Prevention

When it happens

Trigger: Two cluster objects render resources with the same (ResourceType, ResourceName) pair — e.g. two security groups or IAM roles producing identical sanitized names, or names that collide after sanitizeName.

Common situations: Duplicate resources in the cluster spec (e.g. two instance groups with names that sanitize identically); a kOps builder bug registering the same resource twice; name collisions after sanitization strips distinguishing characters.

Related errors


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