hyperledger/fabric · error

failed to parse TickInterval (%s) to time duration: %s

Error message

failed to parse TickInterval (%s) to time duration: %s

What it means

VerifyConfigMetadata guard: the Options.TickInterval string from the etcdraft ConfigMetadata failed time.ParseDuration. The consensus metadata carries a malformed interval (wrong format or non-numeric), and both the raw string and the parse error are reported.

Source

Thrown at orderer/consensus/etcdraft/util.go:232

		return errors.Errorf("nil Raft config metadata options")
	}

	if metadata.GetOptions().GetHeartbeatTick() == 0 ||
		metadata.GetOptions().GetElectionTick() == 0 ||
		metadata.GetOptions().GetMaxInflightBlocks() == 0 {
		// if SnapshotIntervalSize is zero, DefaultSnapshotIntervalSize is used
		return errors.Errorf("none of HeartbeatTick (%d), ElectionTick (%d) and MaxInflightBlocks (%d) can be zero",
			metadata.GetOptions().GetHeartbeatTick(), metadata.GetOptions().GetElectionTick(), metadata.GetOptions().GetMaxInflightBlocks())
	}

	// check Raft options
	if metadata.GetOptions().GetElectionTick() <= metadata.GetOptions().GetHeartbeatTick() {
		return errors.Errorf("ElectionTick (%d) must be greater than HeartbeatTick (%d)",
			metadata.GetOptions().GetElectionTick(), metadata.GetOptions().GetHeartbeatTick())
	}

	if d, err := time.ParseDuration(metadata.GetOptions().GetTickInterval()); err != nil {
		return errors.Errorf("failed to parse TickInterval (%s) to time duration: %s", metadata.GetOptions().GetTickInterval(), err)
	} else if d == 0 {
		return errors.Errorf("TickInterval cannot be zero")
	}

	if len(metadata.GetConsenters()) == 0 {
		return errors.Errorf("empty consenter set")
	}

	// verifying certificates for being signed by CA, expiration is ignored
	for _, consenter := range metadata.GetConsenters() {
		if consenter == nil {
			return errors.Errorf("metadata has nil consenter")
		}
		if err := validateConsenterTLSCerts(consenter, verifyOpts, true); err != nil {
			return errors.WithMessagef(err, "consenter %s:%d has invalid certificate", consenter.GetHost(), consenter.GetPort())
		}
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Set TickInterval to a valid duration string, e.g. "500ms" (Fabric default).
  2. Test the value locally: time.ParseDuration(v) must succeed and be non-zero.
  3. Re-run configtxgen with corrected profile and regenerate the config update.

Example fix

// before
TickInterval: "500"
// after
TickInterval: "500ms"
Defensive patterns

Strategy: validation

Validate before calling

if _, err := time.ParseDuration(metadata.GetOptions().GetTickInterval()); err != nil {
	return fmt.Errorf("TickInterval %q is not a valid duration: %v", metadata.GetOptions().GetTickInterval(), err)
}

Try / catch

if err := VerifyConfigMetadata(meta, opts); err != nil {
	if strings.Contains(err.Error(), "failed to parse TickInterval") {
		return fmt.Errorf("set TickInterval like '500ms' in channel config: %v", err)
	}
	return err
}

Prevention

When it happens

Trigger: TickInterval set to an empty string, a bare number like "500", or a malformed string like "0.5sec" in the channel's Raft options.

Common situations: configtx.yaml TickInterval edited with an unsupported unit; locale/typo issues (e.g. "500ms " with trailing space); tooling writing defaults that leave TickInterval 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/3559d24befdae256. Report an issue: GitHub.