kubernetes/kops · error

BuildFlags of value type not handled: %T %s=%v

Error message

BuildFlags of value type not handled: %T %s=%v

What it means

The flag builder only knows how to render maps of type map[string]string. When reflection reaches a field with a `flag` tag whose underlying value is a Map of any other key/value type, it cannot serialize it and returns this error. It guards against silently emitting malformed flags.

Source

Thrown at pkg/flagbuilder/build_flags.go:119

				return nil
			}
			// We handle a map[string]string like --node-labels=k1=v1,k2=v2 etc
			// As we need more formats we can add additional spec to the flags tag
			if stringStringMap, ok := val.Interface().(map[string]string); ok {
				var args []string
				for k, v := range stringStringMap {
					arg := fmt.Sprintf("%s=%s", k, v)
					args = append(args, arg)
				}
				sort.Strings(args)
				if len(args) != 0 {
					flag := fmt.Sprintf("--%s=%s", flagName, strings.Join(args, ","))
					flags = append(flags, flag)
				}
				return reflectutils.SkipReflection
			}

			return fmt.Errorf("BuildFlags of value type not handled: %T %s=%v", val.Interface(), path, val.Interface())
		}

		if val.Kind() == reflect.Slice {
			if val.IsNil() {
				return nil
			}
			// We handle a []string like --admission-control=v1,v2 etc
			if stringSlice, ok := val.Interface().([]string); ok {
				if len(stringSlice) != 0 {
					if repeatFlag {
						for _, v := range stringSlice {
							flag := fmt.Sprintf("--%s=%s", flagName, v)
							flags = append(flags, flag)
						}
					} else {
						flag := fmt.Sprintf("--%s=%s", flagName, strings.Join(stringSlice, ","))
						flags = append(flags, flag)
					}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Change the field type to map[string]string, converting values to strings when populating it
  2. Remove the `flag` tag from the field if it should not be rendered as a flag
  3. Add a custom branch in the walker for the specific map type if string conversion is safe

Example fix

// before
Taints map[string]int `flag:"taints"`
// after
Taints map[string]string `flag:"taints"`
Defensive patterns

Strategy: validation

Validate before calling

// Ensure flag-tagged map fields are map[string]string before calling BuildFlagsList
if m, ok := opts.SomeMap.(map[string]string); !ok {
	return fmt.Errorf("SomeMap must be map[string]string, got %T", opts.SomeMap)
}

Type guard

func isStringStringMap(v reflect.Value) bool {
	return v.Kind() != reflect.Map || v.Type() == reflect.TypeOf(map[string]string{})
}

Try / catch

flags, err := flagbuilder.BuildFlagsList(opts)
if err != nil {
	if strings.Contains(err.Error(), "value type not handled") {
		log.Fatalf("config field has unsupported type for flag rendering: %v", err)
	}
	return err
}

Prevention

When it happens

Trigger: A field with a `flag` tag is a map[string]int, map[string]bool, map[string][]string, or any non-string-typed map (after pointer dereference), and BuildFlags/BuildFlagsList is called on the options struct.

Common situations: Introducing a new config field with a typed map and forgetting to convert it to map[string]string, or embedding third-party types (e.g. resource maps) into a flaggable struct.

Related errors


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