vitessio/vitess · error
can't get primary replication position: %v
Error message
can't get primary replication position: %v
What it means
getPrimaryPosition calls tmc.PrimaryPosition on the primary tablet to get its current replication position. If the TabletManager RPC fails, this error wraps the cause. It means Vitess reached (or tried to reach) the primary tablet but could not obtain its position.
Source
Thrown at go/vt/mysqlctl/builtinbackupengine.go:1841
}
func (be *BuiltinBackupEngine) Name() string { return builtinBackupEngineName }
func getPrimaryPosition(ctx context.Context, tmc tmclient.TabletManagerClient, ts *topo.Server, keyspace, shard string) (replication.Position, error) {
si, err := ts.GetShard(ctx, keyspace, shard)
if err != nil {
return replication.Position{}, vterrors.Wrap(err, "can't read shard")
}
if topoproto.TabletAliasIsZero(si.PrimaryAlias) {
return replication.Position{}, fmt.Errorf("shard %v/%v has no primary", keyspace, shard)
}
ti, err := ts.GetTablet(ctx, si.PrimaryAlias)
if err != nil {
return replication.Position{}, fmt.Errorf("can't get primary tablet record %v: %v", topoproto.TabletAliasString(si.PrimaryAlias), err)
}
posStr, err := tmc.PrimaryPosition(ctx, ti.Tablet)
if err != nil {
return replication.Position{}, fmt.Errorf("can't get primary replication position: %v", err)
}
pos, err := replication.DecodePosition(posStr)
if err != nil {
return replication.Position{}, fmt.Errorf("can't decode primary replication position %q: %v", posStr, err)
}
return pos, nil
}
func init() {
BackupRestoreEngineMap[builtinBackupEngineName] = &BuiltinBackupEngine{}
}
// closeWithRetry does just what it says. Retrying a close operation is important as
// an error is most likely transient/ephemeral and leaving around open file descriptors
// can lead to later problems as the file may be in a sort-of uploaded state where it
// exists but has not yet been finalized (this is true for GCS). This can cause
// unexpected behavior if you retry the file while the original request is still in this
// state. Most implementations such as GCS will automatically retry operations, but closeView on GitHub (pinned to 01a25a7d17)
Solutions
- Check the primary tablet's health and gRPC port (vtctldclient GetTablet, then hit /debug vars).
- Verify connectivity/auth (certs, grpc port) between the caller and the tablet.
- Confirm mysqld is running on the primary so the agent can read SHOW REPLICA STATUS / binlog position.
- Retry once the tablet is healthy — the failure is often transient.
Defensive patterns
Strategy: retry
Validate before calling
// check tablet reachability before the RPC
if err := checkTabletHealth(ctx, ti.Tablet); err != nil {
return fmt.Errorf("primary tablet unhealthy, skipping position fetch: %w", err)
} Try / catch
pos, err := getPrimaryPosition(ctx, tmc, ts, ks, shard)
if err != nil && strings.Contains(err.Error(), "replication position") {
// transient tablet RPC failure: retry with backoff
pos, err = retryWithBackoff(ctx, func() (replication.Position, error) {
return getPrimaryPosition(ctx, tmc, ts, ks, shard)
})
} Prevention
- Monitor tablet gRPC port reachability and health checks.
- Keep TLS/auth configs consistent between clients and tablets.
- Avoid backups while the primary is restarting or under heavy load.
When it happens
Trigger: tmc.PrimaryPosition(ctx, ti.Tablet) returns an error — tablet agent down, RPC timeout, TLS/auth mismatch between vtctld/vtworker and the tablet, or mysqld unreachable from the tablet agent.
Common situations: Primary tablet process restarting during backup; network partition or firewall blocking the tablet's gRPC port; tablet agent cannot query mysqld for the position.
Related errors
- invalid key:value pair
- Error setting tablet to read-only: %w
- Error setting tablet to read-write: %w
- TabletExternallyReparented failed on primary %v: %v
- tablet %v ResetReplication failed (either fix it, or Scrap i
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/4580ba9ebe59408f.
Report an issue: GitHub.