hyperledger/fabric · error
TickInterval cannot be zero
Error message
TickInterval cannot be zero
What it means
VerifyConfigMetadata guard: Options.TickInterval in the etcdraft ConfigMetadata is set to the zero value. The consensus options must provide a positive tick interval; a missing/zero value is rejected during channel config validation.
Source
Thrown at orderer/consensus/etcdraft/util.go:234
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())
}
}
if err := MetadataHasDuplication(metadata); err != nil {
return errView on GitHub (pinned to 2736b63f8f)
Solutions
- Set a positive TickInterval, e.g. "500ms".
- Validate that parsed duration > 0 before submitting the config update.
- Check profile in configtx.yaml and regenerate config metadata.
Example fix
// before TickInterval: "0s" // after TickInterval: "500ms"
Defensive patterns
Strategy: validation
Validate before calling
d, err := time.ParseDuration(metadata.GetOptions().GetTickInterval())
if err != nil || d <= 0 {
return errors.New("TickInterval must be a positive duration, e.g. 500ms")
} Try / catch
if err := VerifyConfigMetadata(meta, opts); err != nil {
if strings.Contains(err.Error(), "TickInterval cannot be zero") {
return errors.New("configure a positive TickInterval in raft options")
}
return err
} Prevention
- Never set TickInterval to 0/0s.
- Check both parse success and non-zero duration in pre-validation.
- Review generated configs for placeholder values like "0s".
When it happens
Trigger: Options.TickInterval set to "0", "0s", "0ms", or any string that parses to duration 0.
Common situations: Someone tried to 'disable' ticking by zeroing it; generated config leaving TickInterval as "0s"; template placeholder never filled in.
Related errors
- nil Raft config metadata options
- none of HeartbeatTick (%d), ElectionTick (%d) and MaxInfligh
- ElectionTick (%d) must be greater than HeartbeatTick (%d)
- cannot marshal metadata for orderer type %s: %s
- nil metadata
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/7be5831a900198bb.
Report an issue: GitHub.