thanos-io/thanos · error

converting PING response to string

Error message

converting PING response to string

What it means

RedisClient.Ping issues the PING command via rueidis and must convert the reply to a string. If resp.ToString() returns an error (reply is not a simple string), the client returns this fixed error instead of the raw conversion error.

Solutions

  1. Configure the Redis password/credentials if the server requires AUTH.
  2. Wait for Redis to finish loading or check server logs (LOADING Redis is loading the dataset in memory).
  3. Verify the endpoint actually points at a Redis server speaking RESP.
  4. Retry the ping once the server is healthy.

Example fix

// before: no auth configured, PING returns NOAUTH
redis:
  endpoint: redis:6379
// after
redis:
  endpoint: redis:6379
  password: ${REDIS_PASSWORD}
Defensive patterns

Strategy: try-catch

Validate before calling

if err := redisClient.Ping(ctx); err != nil { return fmt.Errorf("redis not ready: %w", err) }

Try / catch

if err := client.Ping(ctx); err != nil {
    if strings.Contains(err.Error(), "converting PING response") {
        // likely NOAUTH or LOADING — check auth config / wait for load
    }
    return err
}

Prevention

When it happens

Trigger: Calling Ping() when the server replies to PING with a non-string type — typically a protocol-level error reply (e.g. NOAUTH, loading dataset) that rueidis returns as a non-string message.

Common situations: Redis requiring auth (requirepass set, no password sent); Redis still loading its RDB/AOF and replying with LOADING errors; connecting to a non-Redis service on the port.

Related errors


AI-assisted analysis of thanos-io/thanos@35b8b99117 (2026-09-07). Data as JSON: /api/errors/53880f90350406e2. Report an issue: GitHub.

Appendix: source

Thrown at internal/cortex/chunk/cache/redis_client.go:98

	return &RedisClient{
		expiration: cfg.Expiration,
		timeout:    cfg.Timeout,
		rdb:        client,
	}, nil
}

func (c *RedisClient) Ping(ctx context.Context) error {
	var cancel context.CancelFunc
	if c.timeout > 0 {
		ctx, cancel = context.WithTimeout(ctx, c.timeout)
		defer cancel()
	}

	resp := c.rdb.Do(ctx, c.rdb.B().Ping().Build())
	pingResp, err := resp.ToString()
	if err != nil {
		return errors.New("converting PING response to string")
	}
	if pingResp != "PONG" {
		return errors.Errorf("redis: Unexpected PING response %q", pingResp)
	}
	return nil
}

func (c *RedisClient) MSet(ctx context.Context, keys []string, values [][]byte) error {
	var cancel context.CancelFunc
	if c.timeout > 0 {
		ctx, cancel = context.WithTimeout(ctx, c.timeout)
		defer cancel()
	}

	if len(keys) != len(values) {
		return errors.Errorf("MSet the length of keys and values not equal, len(keys)=%d, len(values)=%d", len(keys), len(values))
	}

View on GitHub (pinned to 35b8b99117)