kubernetes/kops · error

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

Error message

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

What it means

After maps and slices, the walker switches on scalar/value kinds it can render: string, *string, bool, ints, floats, metav1.Duration and resource.Quantity. A field with a `flag` tag of any other type (e.g. time.Time, custom struct, map-like value type) hits the default case and returns this error.

Source

Thrown at pkg/flagbuilder/build_flags.go:203

			// Go renders a time.Duration to `0` in <= 1.6, and `0s` in >= 1.7
			// We force it to be `0s`, regardless of value
			if vString == "0" {
				vString = "0s"
			}

			if vString != flagEmpty {
				flag = fmt.Sprintf("--%s=%s", flagName, vString)
			}

		case resource.Quantity:
			// Format as a floating point value (i.e. 3.14, not 3140m)
			vString := v.AsDec().String()
			if vString != flagEmpty {
				flag = fmt.Sprintf("--%s=%s", flagName, vString)
			}

		default:
			return fmt.Errorf("BuildFlagsList of value type not handled: %T %s=%v", v, path, v)
		}
		if flag != "" {
			flags = append(flags, flag)
		}

		return reflectutils.SkipReflection
	}
	err := reflectutils.ReflectRecursive(reflect.ValueOf(options), walker, &reflectutils.ReflectOptions{DeprecatedDoubleVisit: true})
	if err != nil {
		return nil, fmt.Errorf("BuildFlagsList to reflect value: %s", err)
	}
	// Sort so that the order is stable across runs
	sort.Strings(flags)

	return flags, nil
}

// maybeQuote quotes s when it contains a double quote, so values survive the space-separated

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Change the field to one of the supported types (string, *string, bool, int/int32/int64, float32/float64, metav1.Duration, resource.Quantity)
  2. Remove the `flag` tag so the field is skipped or descended instead of rendered
  3. Extend the switch at build_flags.go:146-203 to handle the new type

Example fix

// before
IdleTimeout time.Duration `flag:"idle-timeout"`
// after
IdleTimeout metav1.Duration `flag:"idle-timeout"`
Defensive patterns

Strategy: validation

Validate before calling

// Check flag-tagged leaf fields use a supported type before building flags
supported := map[reflect.Type]bool{
	reflect.TypeOf(""): true,
	reflect.TypeOf((*string)(nil)): true,
	reflect.TypeOf(false): true,
	reflect.TypeOf(int32(0)): true,
	reflect.TypeOf(int64(0)): true,
	reflect.TypeOf(metav1.Duration{}): true,
	reflect.TypeOf(resource.Quantity{}): true,
}
v := reflect.ValueOf(opts).FieldByName("IdleTimeout")
if !supported[v.Type()] {
	return fmt.Errorf("field type %s not supported by flagbuilder", v.Type())
}

Type guard

func isFlaggableScalar(v reflect.Value) bool {
	switch v.Interface().(type) {
	case string, *string, bool, int, int32, int64, float32, float64, metav1.Duration, resource.Quantity:
		return true
	}
	return false
}

Try / catch

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

Prevention

When it happens

Trigger: A field with a `flag` tag has a scalar type outside the supported switch, such as time.Time, time.Duration (bare, not metav1.Duration), int8/uint, or a nested struct value reached at leaf position.

Common situations: Using stdlib time.Duration instead of metav1.Duration in a flaggable config struct, adding a new typed field and forgetting the flag tag, or nesting structs that end up as leaves with a `flag` tag.

Related errors


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