{"record":{"id":"4bd92669642ab644","repo":"hyperledger/fabric","slug":"supplied-output-argument-must-be-a-pointer-to-a-st","errorCode":null,"errorMessage":"supplied output argument must be a pointer to a struct but is not pointer","messagePattern":"supplied output argument must be a pointer to a struct but is not pointer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/viperutil/config_util.go","lineNumber":381,"sourceCode":"\t}\n\n\tconfig := factory.GetDefaultOpts()\n\n\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(),","sourceCodeStart":363,"sourceCodeEnd":399,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/viperutil/config_util.go#L363-L399","documentation":"ConfigParser.EnhancedExactUnmarshal unmarshals the loaded viper config into the caller-provided output value via reflection. It requires output to be a pointer so it can write results into it. Passing a non-pointer value makes assignment impossible, so it returns this error immediately.","triggerScenarios":"Calling parser.EnhancedExactUnmarshal(cfgStruct) (value instead of &cfgStruct) from load or any caller; also passing nil or a non-struct pointer would hit this or the companion check.","commonSituations":"Custom tooling reusing viperutil.ConfigParser forgets the ampersand; refactors change output from *CoreConfig to CoreConfig; Go developers used to JSON marshal-into-value APIs.","solutions":["Pass a pointer to your struct: parser.EnhancedExactUnmarshal(&myConfig).","Ensure the pointer targets a struct (see companion error for pointer-to-non-struct).","Check the calling code in common/viperutil config load paths to confirm the intended output type."],"exampleFix":"// before\nvar cfg CoreConfig\nparser.EnhancedExactUnmarshal(cfg)\n// after\nvar cfg CoreConfig\nerr := parser.EnhancedExactUnmarshal(&cfg)","handlingStrategy":"type-guard","validationCode":"if reflect.TypeOf(out) == nil || reflect.TypeOf(out).Kind() != reflect.Pointer {\n    return errors.New(\"EnhancedExactUnmarshal requires 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 err := parser.EnhancedExactUnmarshal(&cfg); err != nil {\n    return fmt.Errorf(\"config unmarshal failed: %w\", err)\n}","preventionTips":["Always pass &cfg when calling EnhancedExactUnmarshal","Use a lint rule or code review check for viperutil call sites","Wrap calls in a small helper that enforces pointer input"],"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"}