vitessio/vitess · error · ErrThrottlerNotOpen (sentinel error)
throttler not open
Error message
throttler not open
What it means
ErrThrottlerNotOpen is the sentinel error returned by the tabletserver throttler when an operation (such as a Check) is attempted before the throttler has been opened (Throttler.Open) or after it has been closed. The throttler must be initialized and opened as part of tabletserver startup before it can serve checks.
Source
Thrown at go/vt/vttablet/tabletserver/throttle/throttler.go:120
)
var throttleTabletTypes = "replica"
var (
statsThrottlerHeartbeatRequests = stats.NewCounter("ThrottlerHeartbeatRequests", "heartbeat requests")
statsThrottlerProbeRecentlyChecked = stats.NewCounter("ThrottlerProbeRecentlyChecked", "probe recently checked")
)
func init() {
servenv.OnParseFor("vtcombo", registerThrottlerFlags)
servenv.OnParseFor("vttablet", registerThrottlerFlags)
}
func registerThrottlerFlags(fs *pflag.FlagSet) {
utils.SetFlagStringVar(fs, &throttleTabletTypes, "throttle-tablet-types", throttleTabletTypes, "Comma separated VTTablet types to be considered by the throttler. default: 'replica'. example: 'replica,rdonly'. 'replica' always implicitly included")
}
var ErrThrottlerNotOpen = errors.New("throttler not open")
// throttlerTopoService represents the functionality we expect from a TopoServer, abstracted so that
// it can be mocked in unit tests
type throttlerTopoService interface {
GetTablet(ctx context.Context, alias *topodatapb.TabletAlias) (*topo.TabletInfo, error)
FindAllTabletAliasesInShard(ctx context.Context, keyspace, shard string) ([]*topodatapb.TabletAlias, error)
GetSrvKeyspace(ctx context.Context, cell, keyspace string) (*topodatapb.SrvKeyspace, error)
}
// Throttler is the main entity in the throttling mechanism. This service runs, probes, collects data,
// aggregates, reads inventory, provides information, etc.
type Throttler struct {
keyspace string
shard string
tabletAlias *topodatapb.TabletAlias
tabletInfo atomic.Pointer[topo.TabletInfo]
check *ThrottlerCheckView on GitHub (pinned to 01a25a7d17)
Solutions
- Ensure the tabletserver (and thus throttler.Open) has finished initialization before issuing throttler checks.
- Retry the check after a short delay — this is typically a transient startup/shutdown race.
- In tests, call throttler.Open() and defer throttler.Close() around usage.
- If persistent, check vttablet logs for throttler initialization failures (e.g. topo errors) preventing Open.
Example fix
// before
res, err := throttleApp.Check(ctx, flags) // may run before throttler opened
// after
if err := th.Open(ctx); err != nil { return err }
res, err := throttleApp.Check(ctx, flags) Defensive patterns
Strategy: retry
Type guard
func (t *Throttler) IsOpen() bool { return atomic.LoadInt32(&t.isOpen) > 0 } Try / catch
if errors.Is(err, throttle.ErrThrottlerNotOpen) {
time.AfterFunc(time.Second, func() { retryCheck(ctx) })
return
} Prevention
- Only issue throttler checks after tabletserver Init completes.
- Use readiness probes so clients don't hit vttablet mid-startup.
- In tests, always Open() the throttler and defer Close().
When it happens
Trigger: Calling throttle.Check / CheckApp before tabletserver.Init completes, or after tabletserver closes the throttler on shutdown; unit tests instantiating a Throttler struct without calling Open.
Common situations: Health-check requests racing tablet startup; vttablet shutting down while VReplication or a custom caller still issues throttler checks; tests constructing throttler by hand.
Related errors
- no app indicated
- VStreamer is not open
- VStreamer is not open
- unknown metric name: %s
- invalid metric name: %s
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/cf252858a53c806e.
Report an issue: GitHub.