Tencent/WeKnora · error

get sandbox binding: %w

Error message

get sandbox binding: %w

What it means

Get fetches the raw binding JSON from Redis by the binding key. A miss (redis.Nil) returns (nil, nil) by design, but any other Redis error — connection failure, timeout, cluster redirect, auth — is wrapped as "get sandbox binding: %w". The caller cannot distinguish store outages from other faults except through the wrapped cause.

Source

Thrown at internal/sandbox/session_binding_redis.go:122

		lockLease:         redisLifecycleLockLease,
		lockRenewInterval: redisLifecycleLockRenewInterval,
	}, nil
}

// Get returns the current binding, or nil when the session is unbound.
func (s *RedisSessionSandboxBindingStore) Get(
	ctx context.Context,
	key SessionSandboxKey,
) (*SessionSandboxBinding, error) {
	if err := key.Validate(); err != nil {
		return nil, err
	}
	raw, err := s.client.Get(ctx, s.bindingKey(key)).Bytes()
	if errors.Is(err, redis.Nil) {
		return nil, nil
	}
	if err != nil {
		return nil, fmt.Errorf("get sandbox binding: %w", err)
	}

	var binding SessionSandboxBinding
	if err := json.Unmarshal(raw, &binding); err != nil {
		return nil, fmt.Errorf("decode sandbox binding: %w", err)
	}
	if err := binding.Validate(key); err != nil {
		return nil, fmt.Errorf("validate sandbox binding: %w", err)
	}
	return &binding, nil
}

// Create stores a validated current-schema binding with SET NX and no
// expiration.
func (s *RedisSessionSandboxBindingStore) Create(
	ctx context.Context,
	key SessionSandboxKey,
	binding SessionSandboxBinding,

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Inspect the wrapped cause; fix connectivity, credentials, or cluster routing as indicated
  2. Retry Get with short backoff for transient Redis failures (timeouts, pool exhaustion)
  3. Confirm REDIS_URL/TLS/auth env configuration matches the deployed Redis topology
  4. For misses, remember redis.Nil returns (nil, nil) — treat that as 'no binding', not this error

Example fix

// before
b, err := store.Get(ctx, key)
if err != nil { return err }
// after
b, err := store.Get(ctx, key)
if err != nil {
    if isRedisTransient(err) { return retryGet(ctx, key) }
    return fmt.Errorf("binding lookup: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

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

Type guard

func bindingExists(b *sandbox.SessionSandboxBinding, err error) bool {
    return err == nil && b != nil // (nil, nil) means miss, not error
}

Try / catch

b, err := store.Get(ctx, key)
if err != nil {
    if isRedisTransient(err) { return retryGet(ctx, key) }
    return fmt.Errorf("binding get: %w", err)
}
if b == nil { return errNoBinding } // redis.Nil miss path

Prevention

When it happens

Trigger: Calling Get while Redis is unreachable, the client's dial/auth settings are wrong, a read timeout elapses, or MOVED/CLUSTER errors occur in clustered deployments.

Common situations: Redis restart or failover mid-session; wrong REDIS_URL/password in the environment; connection pool exhausted under load; network partition between app and Redis.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/e2993a9c3f52156a. Report an issue: GitHub.