{"record":{"id":"bc42cea8873108dd","repo":"vitessio/vitess","slug":"getfuncfortype-does-not-support-channel-types","errorCode":null,"errorMessage":"GetFuncForType does not support channel types","messagePattern":"GetFuncForType does not support channel types","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/viperutil/get_func.go","lineNumber":117,"sourceCode":"\t\t\t\treturn float32(v.GetFloat64(key))\n\t\t\t}\n\t\t}\n\tcase reflect.Float64:\n\t\tf = func(v *viper.Viper) func(key string) float64 {\n\t\t\treturn v.GetFloat64\n\t\t}\n\tcase reflect.Complex64:\n\t\tf = getComplex[complex64](64)\n\tcase reflect.Complex128:\n\t\tf = getComplex[complex128](128)\n\tcase reflect.Array:\n\t\t// Even though the code would be extremely similar to slice types, we\n\t\t// cannot support arrays because there's no way to write a function that\n\t\t// returns, say, [N]int, for some value of N which we only know at\n\t\t// runtime.\n\t\tpanic(\"GetFuncForType does not support array types\")\n\tcase reflect.Chan:\n\t\tpanic(\"GetFuncForType does not support channel types\")\n\tcase reflect.Func:\n\t\tpanic(\"GetFuncForType does not support function types\")\n\tcase reflect.Interface:\n\t\tpanic(\"GetFuncForType does not support interface types (specify a specific implementation type instead)\")\n\tcase reflect.Map:\n\t\tswitch typ.Key().Kind() {\n\t\tcase reflect.String:\n\t\t\tswitch val := typ.Elem(); val.Kind() {\n\t\t\tcase reflect.String:\n\t\t\t\tf = func(v *viper.Viper) func(key string) map[string]string {\n\t\t\t\t\treturn v.GetStringMapString\n\t\t\t\t}\n\t\t\tcase reflect.Slice:\n\t\t\t\tswitch val.Elem().Kind() {\n\t\t\t\tcase reflect.String:\n\t\t\t\t\tf = func(v *viper.Viper) func(key string) map[string][]string {\n\t\t\t\t\t\treturn v.GetStringMapStringSlice\n\t\t\t\t\t}","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/viperutil/get_func.go#L99-L135","documentation":"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.","triggerScenarios":"Calling viperutil.Configure/GetFuncForType with a type parameter like chan struct{} or <-chan struct{} (e.g. someone registers a notification-channel option).","commonSituations":"A developer tries to wire an internal signal channel through the config system instead of passing it as a constructor parameter.","solutions":["Remove the channel from the config layer; pass channels through DI/constructor arguments instead","Configure a primitive or supported type that signals how to construct the channel, and create the channel in code","Provide a custom GetFunc via Configure only if you genuinely need a channel value from viper (not recommended)"],"exampleFix":"// before\nch, _ := viperutil.ConfigureAndGet[ chan struct{} ](v, \"shutdown\")\n// after\nch := make(chan struct{}) // created in code, not config\ncfg, _ := viperutil.ConfigureAndGet[ string ](v, \"shutdown-mode\")","handlingStrategy":"validation","validationCode":"if reflect.TypeOf(optionValue).Kind() == reflect.Chan {\n    return errors.New(\"channels cannot be configured via viper; pass them through code\")\n}","typeGuard":"func isChannelType[T any]() bool {\n    var zero T\n    return reflect.ValueOf(zero).Kind() == reflect.Chan\n}","tryCatchPattern":null,"preventionTips":["Never put chan types in viperutil generic parameters or config structs","Pass channels via constructor/DI, keep config limited to serializable values","If you need shutdown signaling config, use a string/enum option and build the channel in code"],"tags":["go","viper","config","generics","panic"],"backgroundTag":"unsupported-config-type","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}