bytebase/bytebase · error

expect *redis.ClusterClient, but get %T

Error message

expect *redis.ClusterClient, but get %T

What it means

With QueryOption_ALL_NODES, QueryConn must fan a command out to every node of a Redis cluster, so it asserts d.rdb is a *redis.ClusterClient. If the underlying client is a plain Client (standalone/sentinel) instead, the type assertion fails and the error names the actual concrete type received.

Source

Thrown at backend/plugin/db/redis/redis.go:274

			for _, input := range inputs {
				cmd := p.Do(ctx, input...)
				cmds = append(cmds, cmd)
			}
			return nil
		}); err != nil && err != redis.Nil {
			return nil, err
		}

		for i, cmd := range cmds {
			setQueryResultRows(results[i], cmd, queryContext.MaximumSQLResultSize)
			results[i].Latency = durationpb.New(time.Since(startTime))
			results[i].RowsCount = int64(len(results[i].Rows))
		}

	case v1pb.QueryOption_ALL_NODES:
		cluster, ok := d.rdb.(*redis.ClusterClient)
		if !ok {
			return nil, errors.Errorf("expect *redis.ClusterClient, but get %T", d.rdb)
		}

		var cmdss [][]*redis.Cmd
		cmdsChan := make(chan []*redis.Cmd)
		stopChan := make(chan struct{})
		go func() {
			for {
				select {
				case cmds := <-cmdsChan:
					cmdss = append(cmdss, cmds)
				case <-stopChan:
					return
				}
			}
		}()

		err := cluster.ForEachShard(ctx, func(ctx context.Context, client *redis.Client) error {
			var cmds []*redis.Cmd

View on GitHub (pinned to 1870550677)

Solutions

  1. Don't use the ALL_NODES query option unless the instance is a Redis cluster.
  2. Change the instance's redisType to CLUSTER if it truly is a cluster so d.rdb is a ClusterClient.
  3. Re-run the query with the default (single-node) query option instead.

Example fix

// before: ALL_NODES on a standalone instance
queryContext.Option.QueryType = v1pb.QueryOption_ALL_NODES
// after: use default/single-node execution
queryContext.Option.QueryType = v1pb.QueryOption_BASIC
Defensive patterns

Strategy: type-guard

Validate before calling

if qCtx.Option.QueryType == v1pb.QueryOption_ALL_NODES && cfg.DataSource.GetRedisType() != storepb.DataSource_REDIS_TYPE_CLUSTER {
	log.Fatal("ALL_NODES requires a Redis cluster instance")
}

Type guard

cluster, ok := d.rdb.(*redis.ClusterClient)
if !ok {
	return nil, fmt.Errorf("ALL_NODES unsupported: client is %T", d.rdb)
}

Try / catch

results, err := d.QueryConn(ctx, conn, stmt, qCtx)
if err != nil && strings.Contains(err.Error(), "expect *redis.ClusterClient") {
	// fall back to single-node query
}

Prevention

When it happens

Trigger: Executing a query with QueryOption_ALL_NODES against an instance configured as STANDALONE or SENTINEL — the rdb field holds redis.Client/SentinelClient, not redis.ClusterClient.

Common situations: Users selecting the "run on all nodes" option for a non-cluster Redis; instance type misconfigured (configured as standalone but actually cluster, or vice versa).

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06). Data as JSON: /api/errors/fe804a0d296a1571. Report an issue: GitHub.