{"record":{"id":"f5d6a55db84fbbdd","repo":"vitessio/vitess","slug":"no-tablet-picker-configured-for-s-s","errorCode":null,"errorMessage":"no tablet picker configured for %s/%s","messagePattern":"no tablet picker configured for (.+?)/(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vttablet/tabletmanager/vreplication/controller.go","lineNumber":384,"sourceCode":"\t\tTime:    time.Now(),\n\t\tMessage: message,\n\t})\n\tquery := fmt.Sprintf(\"update _vt.vreplication set message=%v where id=%v\", encodeString(binlogplayer.MessageTruncate(message)), ct.id)\n\tif _, err := dbClient.ExecuteFetch(query, 1); err != nil {\n\t\treturn fmt.Errorf(\"could not set message: %v: %v\", query, err)\n\t}\n\treturn nil\n}\n\n// pickSourceTablet picks a healthy serving tablet to source for\n// the vreplication stream. If the source is marked as external, it\n// returns nil.\nfunc (ct *controller) pickSourceTablet(ctx context.Context, dbClient binlogplayer.DBClient) (*topodatapb.Tablet, error) {\n\tif ct.source.GetExternalMysql() != \"\" {\n\t\treturn nil, nil\n\t}\n\tif ct.tpTs == nil {\n\t\treturn nil, fmt.Errorf(\"no tablet picker configured for %s/%s\", ct.source.Keyspace, ct.source.Shard)\n\t}\n\tlog.Info(fmt.Sprintf(\"%s trying to find an eligible source tablet in %s/%s\", ct.logPrefix(), ct.source.Keyspace, ct.source.Shard))\n\n\ttablet, err := ct.pickSourceTabletWithIgnoreList(ctx, dbClient)\n\t// If we failed to find any tablet and we specified an ignore list, then clear the ignore list so that\n\t// we can try tablets that were previously ignored(since some state may have changed since the last attempt).\n\tif err != nil && len(ct.ignoreTablets) > 0 {\n\t\tlog.Info(fmt.Sprintf(\"%s clearing ignore list of %d tablets and retrying tablet picker\",\n\t\t\tct.logPrefix(), len(ct.ignoreTablets)))\n\t\tct.ignoreTablets = nil\n\t\ttablet, err = ct.pickSourceTabletWithIgnoreList(ctx, dbClient)\n\t}\n\tif err != nil {\n\t\treturn tablet, err\n\t}\n\tct.setMessage(dbClient, \"Picked source tablet: \"+tablet.Alias.String())\n\tlog.Info(fmt.Sprintf(\"%s found eligible source tablet %s\", ct.logPrefix(), tablet.Alias.String()))\n\tct.sourceTablet.Store(tablet.Alias)","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vttablet/tabletmanager/vreplication/controller.go#L366-L402","documentation":"pickSourceTablet needs a TabletPicker (ct.tpTs) to find a healthy serving tablet in the source keyspace/shard. If no tablet picker was configured for the controller (and the source is not an external MySQL), it returns `no tablet picker configured for <keyspace>/<shard>`.","triggerScenarios":"A vreplication stream whose source.Keyspace/Shard is set, ExternalMysql is empty, but the controller was created without a tablet picker timestamp source (ct.tpTs == nil) — typically when the local cell has no topology service or the controller was constructed in a code path that skips picker setup.","commonSituations":"Misconfigured MoveTables/Reshard workflow where the source keyspace/shard doesn't exist in the topology; vttablet started without proper cell/topo flags; external MySQL handling changed between versions so the external check no longer short-circuits.","solutions":["Verify the source keyspace and shard exist and have serving tablets in the topology (`vtctldclient GetTablets`).","Check the vttablet flags for cell / topo implementation are correct.","If the source is truly external MySQL, ensure ExternalMysql is set on the stream source so the picker isn't required.","Re-create the workflow with correct source keyspace/shard."],"exampleFix":"// before (stream created against wrong keyspace)\nsourceKeyspace: \"commerce_old\" // does not exist in topo\n// after\nvtctldclient MoveTables --target-keyspace commerce --tables t1 create commerce_old","handlingStrategy":"validation","validationCode":"// Verify serving tablets exist before creating a workflow:\nvtctldclient GetTablets --keyspace commerce --shard 0 | grep -i serving\n# or in Go, check the topo for source keyspace/shard before constructing the controller","typeGuard":null,"tryCatchPattern":"tablet, err := ct.pickSourceTablet(ctx, dbClient)\nif err != nil && strings.Contains(err.Error(), \"no tablet picker configured\") {\n    return vterrors.Errorf(vtrpcpb.Code_FAILED_PRECONDITION, \"source %s/%s not usable: %w\", ks, shard, err)\n}","preventionTips":["Confirm source keyspace/shard exist in topology before MoveTables/Reshard.","Start vttablet with correct --cell and topo flags so a picker can be constructed.","For external MySQL sources, ensure ExternalMysql is properly recorded on the stream."],"tags":["topology","vreplication","configuration"],"backgroundTag":"missing-tablet-picker-config","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}