hyperledger/fabric · error

bad config metadata option LeaderHeartbeatTimeout

Error message

bad config metadata option LeaderHeartbeatTimeout

What it means

ConfigFromMetadataOptions parses LeaderHeartbeatTimeout from the BFT metadata options with time.ParseDuration; on failure it returns this wrapped error. The leader heartbeat timeout controls liveness detection in SmartBFT, so an unparseable value aborts chain creation or the config-block commit.

Source

Thrown at orderer/consensus/smartbft/util/util.go:50

	config.IncomingMessageBufferSize = options.IncomingMessageBufferSize
	config.RequestPoolSize = options.RequestPoolSize
	if config.RequestForwardTimeout, err = time.ParseDuration(options.RequestForwardTimeout); err != nil {
		return config, errors.Wrap(err, "bad config metadata option RequestForwardTimeout")
	}
	if config.RequestComplainTimeout, err = time.ParseDuration(options.RequestComplainTimeout); err != nil {
		return config, errors.Wrap(err, "bad config metadata option RequestComplainTimeout")
	}
	if config.RequestAutoRemoveTimeout, err = time.ParseDuration(options.RequestAutoRemoveTimeout); err != nil {
		return config, errors.Wrap(err, "bad config metadata option RequestAutoRemoveTimeout")
	}
	if config.ViewChangeResendInterval, err = time.ParseDuration(options.ViewChangeResendInterval); err != nil {
		return config, errors.Wrap(err, "bad config metadata option ViewChangeResendInterval")
	}
	if config.ViewChangeTimeout, err = time.ParseDuration(options.ViewChangeTimeout); err != nil {
		return config, errors.Wrap(err, "bad config metadata option ViewChangeTimeout")
	}
	if config.LeaderHeartbeatTimeout, err = time.ParseDuration(options.LeaderHeartbeatTimeout); err != nil {
		return config, errors.Wrap(err, "bad config metadata option LeaderHeartbeatTimeout")
	}
	config.LeaderHeartbeatCount = options.LeaderHeartbeatCount
	if config.CollectTimeout, err = time.ParseDuration(options.CollectTimeout); err != nil {
		return config, errors.Wrap(err, "bad config metadata option CollectTimeout")
	}
	config.SyncOnStart = options.SyncOnStart
	config.SpeedUpViewChange = options.SpeedUpViewChange

	if options.LeaderRotation != smartbft.Options_ROTATION_ON {
		config.LeaderRotation = false
		config.DecisionsPerLeader = 0
	} else {
		config.LeaderRotation = true
		config.DecisionsPerLeader = options.DecisionsPerLeader
	}

	if err = config.Validate(); err != nil {
		return config, errors.Wrap(err, "config validation failed")

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Set LeaderHeartbeatTimeout to a valid duration string, e.g. "10s"
  2. Regenerate the config block from validated BFT options and retry channel update
  3. Run `inspect` against the block to pre-validate metadata options
  4. Ensure the option key is spelled exactly LeaderHeartbeatTimeout in the metadata

Example fix

// before
"LeaderHeartbeatTimeout": ""
// after
"LeaderHeartbeatTimeout": "10s"
Defensive patterns

Strategy: validation

Validate before calling

if _, err := time.ParseDuration(opts.LeaderHeartbeatTimeout); err != nil { return fmt.Errorf("LeaderHeartbeatTimeout invalid: %w", err) }

Try / catch

cfg, err := util.ConfigFromMetadataOptions(selfID, opts)
if err != nil { return fmt.Errorf("rejecting options: %w", err) }

Prevention

When it happens

Trigger: Orderer HandleChain startup, configBlockToBFTConfig during channel update, or `inspect` when options.LeaderHeartbeatTimeout is absent, empty, or not a valid duration string.

Common situations: Operator set the value in a config block as a number or with a wrong unit, generated metadata omitted the field, or tooling wrote a different casing of the key so the field reads empty.

Understand the failure class

Background: "invalid duration" / "failed to parse duration": why your timeout, interval, or TTL string is rejected and which formats each library accepts — this error's family across 32 libraries.

Related errors


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