vitessio/vitess · error

GetKeyspace(%v): %w

Error message

GetKeyspace(%v): %w

What it means

CopyKeyspaces wraps errors from fromTS.GetKeyspace(ctx, keyspace) with the failing keyspace name. The keyspace listing succeeded but reading an individual keyspace record failed. NodeExists on the destination is tolerated with a warning; only errors reading the source abort the copy.

Source

Thrown at go/vt/topo/helpers/copy.go:46

	"vitess.io/vitess/go/vt/sqlparser"
	"vitess.io/vitess/go/vt/topo"
	"vitess.io/vitess/go/vt/topo/topoproto"
	"vitess.io/vitess/go/vt/vtgate/vindexes"

	topodatapb "vitess.io/vitess/go/vt/proto/topodata"
)

// CopyKeyspaces will create the keyspaces in the destination topo.
func CopyKeyspaces(ctx context.Context, fromTS, toTS *topo.Server, parser *sqlparser.Parser) error {
	keyspaces, err := fromTS.GetKeyspaces(ctx)
	if err != nil {
		return fmt.Errorf("GetKeyspaces: %w", err)
	}

	for _, keyspace := range keyspaces {
		ki, err := fromTS.GetKeyspace(ctx, keyspace)
		if err != nil {
			return fmt.Errorf("GetKeyspace(%v): %w", keyspace, err)
		}

		if err := toTS.CreateKeyspace(ctx, keyspace, ki.Keyspace); err != nil {
			if topo.IsErrType(err, topo.NodeExists) {
				log.Warn(fmt.Sprintf("keyspace %v already exists", keyspace))
			} else {
				log.Error(fmt.Sprintf("CreateKeyspace(%v): %v", keyspace, err))
			}
		}

		ksvs, err := fromTS.GetVSchema(ctx, keyspace)
		switch {
		case err == nil:
			_, err = vindexes.BuildKeyspace(ksvs.Keyspace, parser)
			if err != nil {
				log.Error(fmt.Sprintf("BuildKeyspace(%v): %v", keyspace, err))
				break
			}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check the wrapped error type: if topo.NoNode, the keyspace vanished concurrently — re-run the copy after the conflicting operation finishes.
  2. Verify read permissions on the keyspace node in the source topo.
  3. Check source topo backend health if the error is a connection/timeout error.
  4. Re-run CopyKeyspaces; the operation is idempotent (existing keyspaces are skipped with a warning).

Example fix

// before
if err != nil {
	return fmt.Errorf("GetKeyspace(%v): %w", keyspace, err)
}
// after
if err != nil {
	if topo.IsErrType(err, topo.NoNode) {
		log.Warn(fmt.Sprintf("keyspace %v disappeared, skipping", keyspace))
		continue
	}
	return fmt.Errorf("GetKeyspace(%v): %w", keyspace, err)
}
Defensive patterns

Strategy: type-guard

Validate before calling

_, err := fromTS.GetKeyspace(ctx, ks)
if topo.IsErrType(err, topo.NoNode) {
	// keyspace already gone; safe to skip or re-list
}

Type guard

func keyspaceGone(err error) bool {
	return topo.IsErrType(err, topo.NoNode)
}

Try / catch

ki, err := fromTS.GetKeyspace(ctx, keyspace)
if err != nil {
	if topo.IsErrType(err, topo.NoNode) {
		continue
	}
	return fmt.Errorf("GetKeyspace(%v): %w", keyspace, err)
}

Prevention

When it happens

Trigger: Calling CopyKeyspaces when GetKeyspace returns topo.NoNode (keyspace deleted between list and get — a race), a connection error to the source topo, or a corrupt/partial keyspace record that fails unmarshaling.

Common situations: Concurrent topology modification (keyspace removed by a reshard/vtctld operation while the copy runs); stale topo cache; etcd compaction; ACL denying read on a specific keyspace node.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/e894259b21243136. Report an issue: GitHub.