{"record":{"id":"cf252858a53c806e","repo":"vitessio/vitess","slug":"throttler-not-open","errorCode":null,"errorMessage":"throttler not open","messagePattern":"throttler not open","errorType":"exception","errorClass":"ErrThrottlerNotOpen (sentinel error)","httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletserver/throttle/throttler.go","lineNumber":120,"sourceCode":")\n\nvar throttleTabletTypes = \"replica\"\n\nvar (\n\tstatsThrottlerHeartbeatRequests    = stats.NewCounter(\"ThrottlerHeartbeatRequests\", \"heartbeat requests\")\n\tstatsThrottlerProbeRecentlyChecked = stats.NewCounter(\"ThrottlerProbeRecentlyChecked\", \"probe recently checked\")\n)\n\nfunc init() {\n\tservenv.OnParseFor(\"vtcombo\", registerThrottlerFlags)\n\tservenv.OnParseFor(\"vttablet\", registerThrottlerFlags)\n}\n\nfunc registerThrottlerFlags(fs *pflag.FlagSet) {\n\tutils.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\")\n}\n\nvar ErrThrottlerNotOpen = errors.New(\"throttler not open\")\n\n// throttlerTopoService represents the functionality we expect from a TopoServer, abstracted so that\n// it can be mocked in unit tests\ntype throttlerTopoService interface {\n\tGetTablet(ctx context.Context, alias *topodatapb.TabletAlias) (*topo.TabletInfo, error)\n\tFindAllTabletAliasesInShard(ctx context.Context, keyspace, shard string) ([]*topodatapb.TabletAlias, error)\n\tGetSrvKeyspace(ctx context.Context, cell, keyspace string) (*topodatapb.SrvKeyspace, error)\n}\n\n// Throttler is the main entity in the throttling mechanism. This service runs, probes, collects data,\n// aggregates, reads inventory, provides information, etc.\ntype Throttler struct {\n\tkeyspace    string\n\tshard       string\n\ttabletAlias *topodatapb.TabletAlias\n\ttabletInfo  atomic.Pointer[topo.TabletInfo]\n\n\tcheck     *ThrottlerCheck","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletserver/throttle/throttler.go#L102-L138","documentation":"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.","triggerScenarios":"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.","commonSituations":"Health-check requests racing tablet startup; vttablet shutting down while VReplication or a custom caller still issues throttler checks; tests constructing throttler by hand.","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."],"exampleFix":"// before\nres, err := throttleApp.Check(ctx, flags) // may run before throttler opened\n// after\nif err := th.Open(ctx); err != nil { return err }\nres, err := throttleApp.Check(ctx, flags)","handlingStrategy":"retry","validationCode":null,"typeGuard":"func (t *Throttler) IsOpen() bool { return atomic.LoadInt32(&t.isOpen) > 0 }","tryCatchPattern":"if errors.Is(err, throttle.ErrThrottlerNotOpen) {\n  time.AfterFunc(time.Second, func() { retryCheck(ctx) })\n  return\n}","preventionTips":["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()."],"tags":["vitess","throttler","lifecycle","not-open"],"backgroundTag":"service-not-initialized","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}