{"record":{"id":"aee739e94399628c","repo":"vitessio/vitess","slug":"routing-still-exists-from-keyspace-s-table-s-to","errorCode":null,"errorMessage":"routing still exists from keyspace %s table %s to %s","messagePattern":"routing still exists from keyspace (.+?) table (.+?) to (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtctl/workflow/utils.go","lineNumber":596,"sourceCode":"\t\t\t\t}\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\t}\n\twg.Wait()\n\n\tif !ts.keepRoutingRules {\n\t\t// Check if table is routable.\n\t\tif ts.MigrationType() == binlogdatapb.MigrationType_TABLES {\n\t\t\trules, err := topotools.GetRoutingRules(ctx, ts.TopoServer())\n\t\t\tif err != nil {\n\t\t\t\trec.RecordError(errors.New(\"could not get RoutingRules\"))\n\t\t\t}\n\t\t\tfor fromTable, toTables := range rules {\n\t\t\t\tfor _, toTable := range toTables {\n\t\t\t\t\tfor _, table := range ts.Tables() {\n\t\t\t\t\t\tif toTable == fmt.Sprintf(\"%s.%s\", ts.SourceKeyspaceName(), table) {\n\t\t\t\t\t\t\trec.RecordError(fmt.Errorf(\"routing still exists from keyspace %s table %s to %s\", ts.SourceKeyspaceName(), table, fromTable))\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tif rec.HasErrors() {\n\t\treturn fmt.Errorf(\"%s\", strings.Join(rec.ErrorStrings(), \"\\n\"))\n\t}\n\treturn nil\n}\n\n// ReverseWorkflowName returns the \"reversed\" name of a workflow. For a\n// \"forward\" workflow, this is the workflow name with \"_reverse\" appended, and\n// for a \"reversed\" workflow, this is the workflow name with the \"_reverse\"\n// suffix removed.\nfunc ReverseWorkflowName(workflow string) string {\n\tif strings.HasSuffix(workflow, reverseSuffix) {","sourceCodeStart":578,"sourceCodeEnd":614,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctl/workflow/utils.go#L578-L614","documentation":"As a final completion check, the workflow validator reads the current RoutingRules and verifies that no routing rule still points a `fromTable` at a source-keyspace table participating in the workflow. If a rule maps traffic into the source keyspace's table (e.g. customer.t still routed via a MoveTables rule), the migration is not fully cut over and this error is recorded.","triggerScenarios":"Running validateWorkflowHasCompleted (via SwitchTraffic/final validation) while RoutingRules still contain entries mapping a from-table to `sourceKeyspace.table` for a table in the workflow's table set — i.e. the RemoveRoutingRule step never ran or added rules back.","commonSituations":"Finalizing MoveTables before switching routing rules; a second workflow re-adding routing to the source keyspace; partial traffic switch leaving some table rules in place.","solutions":["Run the workflow's traffic-switch/finalize step that removes the routing rules (SwitchTraffic with all tables, or RemoveRoutingRule for the stale entries).","Inspect `vtctldclient GetRoutingRules` and delete rules whose to-tables point at sourceKeyspace.<table>.","Re-run validation after cleaning the rules; it should find no routing into the source keyspace."],"exampleFix":"// before (routing rules still contain)\n//   from: customer.t  ->  [ks1.t]\n// error: routing still exists from keyspace ks1 table t to customer.t\n// after\nvtctldclient RemoveRoutingRule --table=customer.t\nvtctldclient ApplyRoutingRules --rules-file=cleaned.json","handlingStrategy":"validation","validationCode":"// ensure no routing rule targets the source keyspace tables\nrules := getRoutingRules()\nfor from, tos := range rules {\n    for _, to := range tos {\n        if strings.HasPrefix(to, sourceKeyspace+\".\") {\n            return fmt.Errorf(\"stale routing rule %s -> %s\", from, to)\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run GetRoutingRules and clean stale entries before finalizing a workflow.","Complete the full SwitchTraffic sequence so routing rules are removed automatically.","Avoid running overlapping workflows that re-add routing to the source keyspace."],"tags":["go","routing-rules","vreplication","validation"],"backgroundTag":"stale-routing-rules","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}