vitessio/vitess · error
could not get RoutingRules
Error message
could not get RoutingRules
What it means
During workflow-completion validation, when --keep-routing-rules is not set, vtctl reads the global RoutingRules from the topology to verify no routing entries still point at the source keyspace. If reading RoutingRules fails, this error is recorded. Note: rules is then still used in the loop below, which is why a nil/failed read must be treated as fatal.
Source
Thrown at go/vt/vtctl/workflow/utils.go:590
return nil
}
for _, stream := range res.Streams {
if stream.Message != Frozen {
rec.RecordError(fmt.Errorf("vreplication streams are not frozen on tablet %d", target.GetPrimary().Alias.Uid))
return nil
}
}
return nil
})
}
wg.Wait()
if !ts.keepRoutingRules {
// Check if table is routable.
if ts.MigrationType() == binlogdatapb.MigrationType_TABLES {
rules, err := topotools.GetRoutingRules(ctx, ts.TopoServer())
if err != nil {
rec.RecordError(errors.New("could not get RoutingRules"))
}
for fromTable, toTables := range rules {
for _, toTable := range toTables {
for _, table := range ts.Tables() {
if toTable == fmt.Sprintf("%s.%s", ts.SourceKeyspaceName(), table) {
rec.RecordError(fmt.Errorf("routing still exists from keyspace %s table %s to %s", ts.SourceKeyspaceName(), table, fromTable))
}
}
}
}
}
}
if rec.HasErrors() {
return fmt.Errorf("%s", strings.Join(rec.ErrorStrings(), "\n"))
}
return nil
}
View on GitHub (pinned to 01a25a7d17)
Solutions
- Restore topology health and re-run completion validation (vtctldclient Workflow --workflow X MoveTablesComplete)
- Check the topo server connection parameters and permissions of vtctld
- If you intentionally want to keep routing rules, rerun with --keep-routing-rules so the RoutingRules read is skipped
Example fix
// before: read failure recorded but rules used anyway
rules, err := topotools.GetRoutingRules(ctx, ts.TopoServer())
if err != nil {
rec.RecordError(errors.New("could not get RoutingRules"))
}
// after: stop before using possibly-nil rules
rules, err := topotools.GetRoutingRules(ctx, ts.TopoServer())
if err != nil {
rec.RecordError(errors.New("could not get RoutingRules"))
return
} Defensive patterns
Strategy: validation
Validate before calling
rules, err := topotools.GetRoutingRules(ctx, ts.TopoServer())
if err != nil {
return fmt.Errorf("topology unreachable, cannot validate routing rules: %w", err)
} Type guard
if rules == nil {
return errors.New("routing rules not loaded")
} Try / catch
rec := &topo.TopoRecorder{}
validateWorkflowHasCompleted(ctx, ts, wf)
for _, e := range rec.ErrorMessages() {
if strings.Contains(e, "could not get RoutingRules") {
return fmt.Errorf("fix topo server and retry completion validation: %s", e)
}
} Prevention
- Verify topo server health before running MoveTablesComplete
- Use --keep-routing-rules only deliberately, never as a workaround for topo outages
- Read routing rules in a retry loop with short backoff during validation
When it happens
Trigger: Calling validateWorkflowHasCompleted (CompletionValidation for MoveTables) when topotools.GetRoutingRules fails — usually a topology read error (topo server unreachable, etcd/zookeeper down, permission problem) — while keepRoutingRules is false and MigrationType is TABLES.
Common situations: Topology backend outage or degraded quorum during cutover, wrong topo flags on vtctld, stale topo data preventing the RoutingRules global key from being read.
Related errors
- no primary found for shard
- source shard %v is not in serving state
- target shard %v has no primary tablet
- no primary tablet found for materialization workflow %s and
- %w in keyspace %s for %s
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/7300061567c1f0e8.
Report an issue: GitHub.