kubernetes/kops · error

unhandled type %q

Error message

unhandled type %q

What it means

setType supports only map[string]string, map[string]intstr.IntOrString, and map[string][]string for map-typed fields; any other map value type falls into the default branch and errors with the concrete Go type name. Scalar/struct leaves outside the known switch also land here when the string cannot be converted.

Source

Thrown at util/pkg/reflectutils/access.go:181

		case "map[string]intstr.IntOrString":
			name, value, _ := strings.Cut(newValue, "=")
			v.SetMapIndex(reflect.ValueOf(name), reflect.ValueOf(intstr.Parse(value)))

		case "map[string][]string":
			name, value, _ := strings.Cut(newValue, "=")
			tokens := strings.Split(value, ",")
			valueArray := reflect.MakeSlice(reflect.TypeOf(tokens), 0, v.Len()+len(tokens))
			for _, s := range tokens {
				valueItem := reflect.New(reflect.TypeOf(s))
				if err := setType(valueItem.Elem(), s); err != nil {
					return err
				}
				valueArray = reflect.Append(valueArray, valueItem.Elem())
			}
			v.SetMapIndex(reflect.ValueOf(name), valueArray)

		default:
			return fmt.Errorf("unhandled type %q", t)
		}

		return nil
	}

	var newV reflect.Value

	switch t {
	case "string":
		newV = reflect.ValueOf(newValue)

	case "bool":
		b, err := strconv.ParseBool(newValue)
		if err != nil {
			return fmt.Errorf("cannot interpret %q value as bool", newValue)
		}
		newV = reflect.ValueOf(b)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Set the field directly in Go code instead of via SetString.
  2. Change the struct field to a supported map type (map[string]string).
  3. Extend setType with a case for the new type if you own the code.
  4. Use a JSON/YAML edit of the manifest instead of the reflective setter.

Example fix

// before
Counters map[string]int   // setType: unhandled type "map[string]int"
// after
Counters map[string]string // set with "key=1"
Defensive patterns

Strategy: type-guard

Validate before calling

switch t.(type) {
case map[string]string, map[string][]string, map[string]intstr.IntOrString:
    // supported
default:
    rv := reflect.ValueOf(t)
    if rv.Kind() == reflect.Map {
        return fmt.Errorf("unsupported map type %T for SetString", t)
    }
}

Type guard

func isSupportedMap(v interface{}) bool {
    switch v.(type) {
    case map[string]string, map[string][]string, map[string]intstr.IntOrString:
        return true
    }
    return false
}

Try / catch

if err := SetString(&obj, path, val); err != nil {
    var ue *unhandledTypeError // or string match on "unhandled type"
    if strings.HasPrefix(err.Error(), "unhandled type") {
        return fmt.Errorf("field %q has a type SetString cannot write; set it directly", path)
    }
    return err
}

Prevention

When it happens

Trigger: SetString on a field whose type is an unsupported map (e.g. map[string]int, map[string]CustomType) or an unsupported struct/slice leaf type that is not convertible from string.

Common situations: New kOps API fields with exotic map types used with `kops set`; custom addons config using map[string]interface{} (not supported at all).

Related errors


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