vitessio/vitess · error

GetFuncForType does not support channel types

Error message

GetFuncForType does not support channel types

What it means

GetFuncForType[T] in go/viperutil refuses channel-typed configuration values. Viper cannot meaningfully Get a channel from file/flag/env config sources, so the function panics on reflect.Chan instead of silently returning a nil or broken channel.

Source

Thrown at go/viperutil/get_func.go:117

				return float32(v.GetFloat64(key))
			}
		}
	case reflect.Float64:
		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
					}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Remove the channel from the config layer; pass channels through DI/constructor arguments instead
  2. Configure a primitive or supported type that signals how to construct the channel, and create the channel in code
  3. Provide a custom GetFunc via Configure only if you genuinely need a channel value from viper (not recommended)

Example fix

// before
ch, _ := viperutil.ConfigureAndGet[ chan struct{} ](v, "shutdown")
// after
ch := make(chan struct{}) // created in code, not config
cfg, _ := viperutil.ConfigureAndGet[ string ](v, "shutdown-mode")
Defensive patterns

Strategy: validation

Validate before calling

if reflect.TypeOf(optionValue).Kind() == reflect.Chan {
    return errors.New("channels cannot be configured via viper; pass them through code")
}

Type guard

func isChannelType[T any]() bool {
    var zero T
    return reflect.ValueOf(zero).Kind() == reflect.Chan
}

Prevention

When it happens

Trigger: Calling viperutil.Configure/GetFuncForType with a type parameter like chan struct{} or <-chan struct{} (e.g. someone registers a notification-channel option).

Common situations: A developer tries to wire an internal signal channel through the config system instead of passing it as a constructor parameter.

Related errors


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