vitessio/vitess · error

GetFuncForType does not support interface types (specify a s

Error message

GetFuncForType does not support interface types (specify a specific implementation type instead)

What it means

GetFuncForType[T] cannot infer which concrete implementation to construct for an interface-typed value: viper would return raw data with no way to choose the implementing type. It panics with a hint to specify a specific implementation type instead.

Source

Thrown at go/viperutil/get_func.go:121

		f = func(v *viper.Viper) func(key string) float64 {
			return v.GetFloat64
		}
	case reflect.Complex64:
		f = getComplex[complex64](64)
	case reflect.Complex128:
		f = getComplex[complex128](128)
	case reflect.Array:
		// Even though the code would be extremely similar to slice types, we
		// cannot support arrays because there's no way to write a function that
		// returns, say, [N]int, for some value of N which we only know at
		// runtime.
		panic("GetFuncForType does not support array types")
	case reflect.Chan:
		panic("GetFuncForType does not support channel types")
	case reflect.Func:
		panic("GetFuncForType does not support function types")
	case reflect.Interface:
		panic("GetFuncForType does not support interface types (specify a specific implementation type instead)")
	case reflect.Map:
		switch typ.Key().Kind() {
		case reflect.String:
			switch val := typ.Elem(); val.Kind() {
			case reflect.String:
				f = func(v *viper.Viper) func(key string) map[string]string {
					return v.GetStringMapString
				}
			case reflect.Slice:
				switch val.Elem().Kind() {
				case reflect.String:
					f = func(v *viper.Viper) func(key string) map[string][]string {
						return v.GetStringMapStringSlice
					}
				}
			case reflect.Interface:
				f = func(v *viper.Viper) func(key string) map[string]any {
					return v.GetStringMap

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Use a concrete type as the generic parameter (e.g. *bytes.Buffer rather than io.Reader) and store it in an interface-typed variable afterward
  2. Store a discriminator string in config (e.g. implementation name) and map it to a constructor in code
  3. Pass a custom GetFunc via viperutil.Configure that unmarshals and constructs the right implementation

Example fix

// before
r, _ := viperutil.ConfigureAndGet[ io.Reader ](v, "input")
// after
s, _ := viperutil.ConfigureAndGet[ string ](v, "input-file")
r, err := os.Open(s)
Defensive patterns

Strategy: validation

Validate before calling

t := reflect.TypeOf(optionValue)
if t != nil && t.Kind() == reflect.Interface {
    return errors.New("specify a concrete implementation type for viperutil options")
}

Type guard

func isInterfaceType[T any]() bool {
    var zero T
    tt := reflect.TypeOf(zero)
    return tt != nil && tt.Kind() == reflect.Interface
}

Prevention

When it happens

Trigger: Calling viperutil.Configure/GetFuncForType with an interface type parameter (e.g. io.Reader, net.Addr, or a project interface) instead of a concrete type.

Common situations: A developer models a pluggable config option by its interface type and expects the config layer to pick the implementation from config values.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/2ff72936da63e051. Report an issue: GitHub.