{"record":{"id":"3b003debff74d9b5","repo":"hyperledger/fabric","slug":"supplied-output-argument-must-be-a-pointer-to-a-st-3b003d","errorCode":null,"errorMessage":"supplied output argument must be a pointer to a struct, but it is pointer to something else","messagePattern":"supplied output argument must be a pointer to a struct, but it is pointer to something else","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/viperutil/config_util.go","lineNumber":385,"sourceCode":"\terr := mapstructure.WeakDecode(data, config)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"could not decode bccsp type\")\n\t}\n\n\treturn config, nil\n}\n\n// EnhancedExactUnmarshal is intended to unmarshal a config file into a structure\n// producing error when extraneous variables are introduced and supporting\n// the time.Duration type\nfunc (c *ConfigParser) EnhancedExactUnmarshal(output any) error {\n\toType := reflect.TypeOf(output)\n\tif oType.Kind() != reflect.Pointer {\n\t\treturn errors.Errorf(\"supplied output argument must be a pointer to a struct but is not pointer\")\n\t}\n\teType := oType.Elem()\n\tif eType.Kind() != reflect.Struct {\n\t\treturn errors.Errorf(\"supplied output argument must be a pointer to a struct, but it is pointer to something else\")\n\t}\n\n\tbaseKeys := c.config\n\tleafKeys := getKeysRecursively(\"\", c.getFromEnv, baseKeys, eType)\n\n\tlogger.Debugf(\"%+v\", leafKeys)\n\tconfig := &mapstructure.DecoderConfig{\n\t\tErrorUnused:      true,\n\t\tMetadata:         nil,\n\t\tResult:           output,\n\t\tWeaklyTypedInput: true,\n\t\tDecodeHook: mapstructure.ComposeDecodeHookFunc(\n\t\t\tbccspHook,\n\t\t\tmapstructure.StringToTimeDurationHookFunc(),\n\t\t\tcustomDecodeHook,\n\t\t\tbyteSizeDecodeHook,\n\t\t\tstringFromFileDecodeHook,\n\t\t\tpemBlocksFromFileDecodeHook,","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/viperutil/config_util.go#L367-L403","documentation":"After confirming output is a pointer, EnhancedExactUnmarshal checks that the pointed-to element type is a struct, since it builds leaf keys from the struct's fields via getKeysRecursively. A pointer to anything else (map, slice, string) cannot be reflected into the exact-key unmarshal machinery, so this error is returned.","triggerScenarios":"Calling parser.EnhancedExactUnmarshal(&someMap) or &someSlice; passing **struct double pointers may also fail the kind checks depending on reflection handling.","commonSituations":"Developers try to unmarshal into map[string]any to 'just get everything', but EnhancedExactUnmarshal deliberately targets structs; generic wrapper functions using any erase the struct type.","solutions":["Define a target struct matching your config keys and pass its pointer.","If you need dynamic maps, use plain viper.Get/mapstructure decode instead of EnhancedExactUnmarshal.","If using generics/any, assert the concrete struct pointer type before calling."],"exampleFix":"// before\nout := map[string]any{}\nparser.EnhancedExactUnmarshal(&out)\n// after\ntype MyConfig struct { Peer string }\nout := MyConfig{}\nparser.EnhancedExactUnmarshal(&out)","handlingStrategy":"type-guard","validationCode":"t := reflect.TypeOf(out)\nif t == nil || t.Kind() != reflect.Pointer || t.Elem().Kind() != reflect.Struct {\n    return errors.New(\"output must be a pointer to a struct\")\n}","typeGuard":"func isStructPointer(v any) bool {\n    t := reflect.TypeOf(v)\n    return t != nil && t.Kind() == reflect.Pointer && t.Elem().Kind() == reflect.Struct\n}","tryCatchPattern":"if !isStructPointer(&out) { /* restructure */ }\nif err := parser.EnhancedExactUnmarshal(&out); err != nil {\n    return fmt.Errorf(\"config unmarshal failed: %w\", err)\n}","preventionTips":["Define a struct type that mirrors your config keys before unmarshaling","Avoid unmarshaling into map[string]any with EnhancedExactUnmarshal; use plain viper instead","Beware of generic wrappers that erase struct types with any"],"tags":["reflection","api-misuse","viper"],"backgroundTag":"non-pointer-output-argument","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}