{"record":{"id":"c3374465d5188328","repo":"vitessio/vitess","slug":"cell-mode-should-be-handled-by-the-gateway-not-th","errorCode":null,"errorMessage":"cell mode should be handled by the gateway, not the balancer factory","messagePattern":"cell mode should be handled by the gateway, not the balancer factory","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/balancer/balancer.go","lineNumber":165,"sourceCode":"// Supported modes:\n//   - \"prefer-cell\": Flow-based balancer that maintains cell affinity while balancing load\n//   - See the RFC here: https://github.com/vitessio/vitess/issues/12241\n//   - \"random\": Random balancer that uniformly distributes load without cell affinity\n//   - \"session\": Session balancer that pins a session to the same tablet for the duration of the session. If the tablet goes away, the session is automatically and transparently migrated to another tablet of the same type.\n//\n// Note: \"cell\" mode is handled by the gateway and does not create a balancer instance.\n// operates as a round robin inside of the vtgate's cell\n// Returns an error for unsupported modes.\nfunc NewTabletBalancer(mode Mode, localCell string, vtGateCells []string) (TabletBalancer, error) {\n\tswitch mode {\n\tcase ModePreferCell:\n\t\treturn newFlowBalancer(localCell, vtGateCells), nil\n\tcase ModeRandom:\n\t\treturn newRandomBalancer(localCell, vtGateCells), nil\n\tcase ModeSession:\n\t\treturn newSessionBalancer(localCell), nil\n\tcase ModeCell:\n\t\treturn nil, errors.New(\"cell mode should be handled by the gateway, not the balancer factory\")\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"unsupported balancer mode: %s (supported modes: %s)\", mode, strings.Join(GetAvailableModeNames(), \", \"))\n\t}\n}\n\nfunc newFlowBalancer(localCell string, vtGateCells []string) TabletBalancer {\n\treturn &flowBalancer{\n\t\tlocalCell:   localCell,\n\t\tvtGateCells: vtGateCells,\n\t\tallocations: map[discovery.KeyspaceShardTabletType]*targetAllocation{},\n\t}\n}\n\ntype flowBalancer struct {\n\t//\n\t// Configuration\n\t//\n","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/balancer/balancer.go#L147-L183","documentation":"NewTabletBalancer is the balancer factory that maps a configured balancer Mode to a TabletBalancer implementation. ModeCell is special: cell-local routing is handled by the vtgate gateway itself, so requesting a cell balancer from this factory is explicitly rejected rather than returning a broken implementation.","triggerScenarios":"Calling NewTabletBalancer with Mode==ModeCell, e.g. a config that sets the balancer mode to 'cell' when constructing a tablet balancer.","commonSituations":"Misreading documentation and setting the gateway balancer mode to 'cell' expecting the factory to create it; leftover config from an older setup where cell routing was configured differently.","solutions":["Remove the cell mode setting and let the gateway handle cell-local routing","Use one of the supported modes (flow, random, session) in the balancer config","If cell-aware routing is desired, configure it at the gateway level, not via the balancer factory"],"exampleFix":"// before\nbalancer, err := balancer.NewTabletBalancer(ctx, localCell, vtGateCells, balancer.ModeCell)\n// after\nbalancer, err := balancer.NewTabletBalancer(ctx, localCell, vtGateCells, balancer.ModeRandom)","handlingStrategy":"validation","validationCode":"if mode == balancer.ModeCell {\n    return errors.New(\"cell mode must be handled by the gateway; choose another mode\")\n}\nbalancer, err := balancer.NewTabletBalancer(ctx, localCell, vtGateCells, mode)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate balancer mode against GetAvailableModeNames()/supported modes before calling the factory","Keep cell-local routing configuration at the gateway layer","Add a unit test covering every Mode value the factory rejects"],"tags":["vtgate","balancer","config"],"backgroundTag":"unsupported-mode-configured","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}