hyperledger/fabric · error

supplied output argument must be a pointer to a struct but i

Error message

supplied output argument must be a pointer to a struct but is not pointer

What it means

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.

Source

Thrown at common/viperutil/config_util.go:381

	}

	config := factory.GetDefaultOpts()

	err := mapstructure.WeakDecode(data, config)
	if err != nil {
		return nil, errors.Wrap(err, "could not decode bccsp type")
	}

	return config, nil
}

// EnhancedExactUnmarshal is intended to unmarshal a config file into a structure
// producing error when extraneous variables are introduced and supporting
// the time.Duration type
func (c *ConfigParser) EnhancedExactUnmarshal(output any) error {
	oType := reflect.TypeOf(output)
	if oType.Kind() != reflect.Pointer {
		return errors.Errorf("supplied output argument must be a pointer to a struct but is not pointer")
	}
	eType := oType.Elem()
	if eType.Kind() != reflect.Struct {
		return errors.Errorf("supplied output argument must be a pointer to a struct, but it is pointer to something else")
	}

	baseKeys := c.config
	leafKeys := getKeysRecursively("", c.getFromEnv, baseKeys, eType)

	logger.Debugf("%+v", leafKeys)
	config := &mapstructure.DecoderConfig{
		ErrorUnused:      true,
		Metadata:         nil,
		Result:           output,
		WeaklyTypedInput: true,
		DecodeHook: mapstructure.ComposeDecodeHookFunc(
			bccspHook,
			mapstructure.StringToTimeDurationHookFunc(),

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Pass a pointer to your struct: parser.EnhancedExactUnmarshal(&myConfig).
  2. Ensure the pointer targets a struct (see companion error for pointer-to-non-struct).
  3. Check the calling code in common/viperutil config load paths to confirm the intended output type.

Example fix

// before
var cfg CoreConfig
parser.EnhancedExactUnmarshal(cfg)
// after
var cfg CoreConfig
err := parser.EnhancedExactUnmarshal(&cfg)
Defensive patterns

Strategy: type-guard

Validate before calling

if reflect.TypeOf(out) == nil || reflect.TypeOf(out).Kind() != reflect.Pointer {
    return errors.New("EnhancedExactUnmarshal requires a pointer to a struct")
}

Type guard

func isStructPointer(v any) bool {
    t := reflect.TypeOf(v)
    return t != nil && t.Kind() == reflect.Pointer && t.Elem().Kind() == reflect.Struct
}

Try / catch

if err := parser.EnhancedExactUnmarshal(&cfg); err != nil {
    return fmt.Errorf("config unmarshal failed: %w", err)
}

Prevention

When it happens

Trigger: 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.

Common situations: Custom tooling reusing viperutil.ConfigParser forgets the ampersand; refactors change output from *CoreConfig to CoreConfig; Go developers used to JSON marshal-into-value APIs.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/4bd92669642ab644. Report an issue: GitHub.