kubernetes/kops · error

SSH key task has unexpected type %T

Error message

SSH key task has unexpected type %T

What it means

Returned by HCloudSSHKey when the first task of type "SSHKey" in the task map is not actually a *hetznertasks.SSHKey. TasksByType matches by type name string, so a different task type registered under the same name (or a custom/wrapped SSHKey implementation) triggers this type-assertion failure.

Source

Thrown at upup/pkg/fi/cloudup/template_functions.go:1270

	// Strip the trailing newline that json.Encoder.Encode appends.
	return strings.TrimRight(buf.String(), "\n"), nil
}

// HCloudSSHKey returns HCLOUD_SSH_KEY as the first SSH key ID.
func (tf *TemplateFunctions) HCloudSSHKey() (string, error) {
	tasks, err := tf.TasksByType("SSHKey")
	if err != nil {
		return "", fmt.Errorf("listing SSH key tasks: %w", err)
	}
	if len(tasks) == 0 {
		return "", nil
	}

	// Use the first SSH key, since the autoscaler accepts a single HCLOUD_SSH_KEY.
	sshKey, ok := tasks[0].(*hetznertasks.SSHKey)
	if !ok {
		return "", fmt.Errorf("SSH key task has unexpected type %T", tasks[0])
	}

	if sshKey.ID != nil {
		return strconv.FormatInt(fi.ValueOf(sshKey.ID), 10), nil
	}

	return "", nil
}

// HCloudClusterConfigChecksum returns a sha256 checksum of the rendered JSON config.
func (tf *TemplateFunctions) HCloudClusterConfigChecksum() (string, error) {
	jsonConfig, err := tf.HCloudClusterConfig()
	if err != nil {
		return "", err
	}

	sum256 := sha256.Sum256([]byte(jsonConfig))
	return fmt.Sprintf("%x", sum256), nil

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Log %T of the offending task to see its actual concrete type
  2. Ensure only *hetznertasks.SSHKey from the hetznertasks package is registered as an SSHKey task
  3. Remove wrappers/mocks from the production task map
  4. Align vendored hetzner task package versions with kops

Example fix

// before: custom wrapper registered as SSHKey
tasks["SSHKey"] = &mySSHKeyWrapper{...}
// after
var key *hetznertasks.SSHKey = &hetznertasks.SSHKey{Name: fi.PtrTo("default"), ...}
tasks["SSHKey"] = key
Defensive patterns

Strategy: type-guard

Validate before calling

tasks, err := tf.TasksByType("SSHKey")
if err != nil { return err }
if len(tasks) > 0 {
	if _, ok := tasks[0].(*hetznertasks.SSHKey); !ok {
		return fmt.Errorf("SSHKey task is %T, not *hetznertasks.SSHKey", tasks[0])
	}
}

Type guard

func isHetznerSSHKey(t fi.Task) (*hetznertasks.SSHKey, bool) {
	key, ok := t.(*hetznertasks.SSHKey)
	return key, ok
}

Try / catch

sshKeyID, err := tf.HCloudSSHKey()
if err != nil {
	return fmt.Errorf("ssh key type mismatch: %w", err)
}

Prevention

When it happens

Trigger: A task registered with type name "SSHKey" is of a concrete type other than *hetznertasks.SSHKey — e.g. a vendored/renamed SSHKey type, a wrapper struct, or a mock leaking into the build.

Common situations: Forking or wrapping hetznertasks.SSHKey and forgetting to keep the registered type; test doubles injected into the task map; kops/hetzner provider version drift where the task type moved packages.

Related errors


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