hyperledger/fabric · critical

failed to parse TickInterval (%s) to time duration

Error message

failed to parse TickInterval (%s) to time duration

What it means

HandleChain (orderer/consensus/etcdraft/consenter.go:167) parses the TickInterval string from the channel's etcdraft Options into a time.Duration when no TickIntervalOverride is set in the orderer's local config. If the string is not a valid Go duration (e.g. '500' without unit), this error is returned and the chain cannot start. The value originates from channel consensus metadata, so bad metadata breaks all orderers on that channel.

Source

Thrown at orderer/consensus/etcdraft/consenter.go:167

		return nil, errors.Wrap(err, "without a system channel, a follower should have been created")
	}

	var evictionSuspicion time.Duration
	if c.EtcdRaftConfig.EvictionSuspicion == "" {
		c.Logger.Infof("EvictionSuspicion not set, defaulting to %v", DefaultEvictionSuspicion)
		evictionSuspicion = DefaultEvictionSuspicion
	} else {
		evictionSuspicion, err = time.ParseDuration(c.EtcdRaftConfig.EvictionSuspicion)
		if err != nil {
			c.Logger.Panicf("Failed parsing Consensus.EvictionSuspicion: %s: %v", c.EtcdRaftConfig.EvictionSuspicion, err)
		}
	}

	var tickInterval time.Duration
	if c.EtcdRaftConfig.TickIntervalOverride == "" {
		tickInterval, err = time.ParseDuration(m.GetOptions().GetTickInterval())
		if err != nil {
			return nil, errors.Errorf("failed to parse TickInterval (%s) to time duration", m.GetOptions().GetTickInterval())
		}
	} else {
		tickInterval, err = time.ParseDuration(c.EtcdRaftConfig.TickIntervalOverride)
		if err != nil {
			return nil, errors.WithMessage(err, "failed parsing Consensus.TickIntervalOverride")
		}
		c.Logger.Infof("TickIntervalOverride is set, overriding channel configuration tick interval to %v", tickInterval)
	}

	opts := Options{
		RPCTimeout:    c.OrdererConfig.General.Cluster.RPCTimeout,
		RaftID:        id,
		Clock:         clock.NewClock(),
		MemoryStorage: raft.NewMemoryStorage(),
		Logger:        c.Logger,

		TickInterval:         tickInterval,
		ElectionTick:         int(m.GetOptions().GetElectionTick()),

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Fix Options.TickInterval in the channel config to a valid duration string like "500ms" and resubmit via config update (or regenerate genesis)
  2. Alternatively set Orderer.EtcdRaftConfig.TickIntervalOverride (e.g. General.Consensus etcdraft TickInterval in orderer.yaml) to a valid duration to bypass the metadata value
  3. Validate with Go semantics: number plus unit (ns, us, ms, s, m, h) is required

Example fix

// before (channel config metadata)
Options: {TickInterval: "500"}
// after
Options: {TickInterval: "500ms"} // or in orderer.yaml: TickIntervalOverride: 500ms
Defensive patterns

Strategy: validation

Validate before calling

if _, err := time.ParseDuration(raftOptions.GetTickInterval()); err != nil {
    return fmt.Errorf("TickInterval %q is not a valid Go duration (e.g. \"500ms\"): %w", raftOptions.GetTickInterval(), err)
}

Type guard

func tickIntervalValid(s string) bool {
    _, err := time.ParseDuration(s)
    return s != "" && err == nil
}

Try / catch

chain, err := consenter.HandleChain(support, metadata)
if err != nil {
    if strings.Contains(err.Error(), "failed to parse TickInterval") {
        // fix Options.TickInterval in channel config or set TickIntervalOverride in orderer.yaml
    }
}

Prevention

When it happens

Trigger: Channel consensus metadata Options.TickInterval is a string that time.ParseDuration cannot parse (missing time unit, empty string, or non-numeric), while EtcdRaftConfig.TickIntervalOverride is unset.

Common situations: Writing TickInterval: "500" or "500ms abc" in the raft Options of a custom config; hand-editing metadata and dropping the 'ms'/'s' suffix; empty TickInterval in a migrated config.

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/6b44a458f97ae719. Report an issue: GitHub.