kubernetes/kops · error

cannot set value

Error message

cannot set value

What it means

setType is the low-level setter used by SetString; it refuses to write when v.CanSet() is false, meaning the reflect.Value is not addressable. This guards against mutating unexported fields or values obtained from non-pointer targets.

Source

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

		return nil
	}

	err = ReflectRecursive(targetValue, visitor, &ReflectOptions{JSONNames: true})
	if err != nil {
		return err
	}

	if !fieldSet {
		return fmt.Errorf("field %s not found in %s", targetPath, BuildTypeName(reflect.TypeOf(target)))
	}

	return nil
}

func setType(v reflect.Value, newValue string) error {
	if !v.CanSet() {
		return fmt.Errorf("cannot set value")
	}

	if v.Type().Kind() == reflect.Slice {
		// To support multiple values, we split on commas.
		// We have no way to escape a comma currently; but in general we prefer having a slice in the schema,
		// rather than having values that need to be parsed, so we may not need it.
		tokens := strings.Split(newValue, ",")
		valueArray := reflect.MakeSlice(v.Type(), 0, v.Len()+len(tokens))
		valueArray = reflect.AppendSlice(valueArray, v)
		for _, s := range tokens {
			valueItem := reflect.New(v.Type().Elem())
			if err := setType(valueItem.Elem(), s); err != nil {
				return err
			}
			valueArray = reflect.Append(valueArray, valueItem.Elem())
		}
		reflect.New(v.Type().Elem())
		v.Set(valueArray)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Pass a pointer to the top-level struct to SetString.
  2. Make the target field exported in the struct definition.
  3. Copy the object to a locally addressable variable (&obj) before mutating.

Example fix

// before
reflectutils.SetString(cfg, "spec.field", "x")     // cfg is a struct value
// after
reflectutils.SetString(&cfg, "spec.field", "x")
Defensive patterns

Strategy: validation

Validate before calling

v := reflect.ValueOf(target)
if v.Kind() != reflect.Ptr || v.IsNil() {
    return errors.New("target must be an addressable pointer")
}

Type guard

func isAddressable(target interface{}) bool {
    v := reflect.ValueOf(target)
    return v.Kind() == reflect.Ptr && v.Elem().CanSet()
}

Try / catch

if err := SetString(&obj, path, val); err != nil {
    if err.Error() == "cannot set value" || strings.Contains(err.Error(), "cannot set value") {
        return fmt.Errorf("field %q is not settable (unexported or non-addressable)", path)
    }
    return err
}

Prevention

When it happens

Trigger: SetString reaching the matched leaf through an unexported field, or being handed a non-addressable value (struct passed by value, map value, interface holding a copy).

Common situations: Calling SetString(&structByValue,...) where an intermediate field is unexported; using SetString on values pulled from maps or slices of non-pointer elements.

Related errors


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