Tencent/WeKnora · critical
create sandbox binding: %w
Error message
create sandbox binding: %w
What it means
Returned by RedisSessionSandboxBindingStore.Create when the client.SetNX call itself fails — Redis is unreachable, the context is cancelled/timed out, the connection dropped, or the server returned an error (e.g. READONLY on a replica). The binding was NOT stored. Wrapped as 'create sandbox binding: %w'. A returned (false, nil) means the key already existed (no error).
Source
Thrown at internal/sandbox/session_binding_redis.go:151
}
// Create stores a validated current-schema binding with SET NX and no
// expiration.
func (s *RedisSessionSandboxBindingStore) Create(
ctx context.Context,
key SessionSandboxKey,
binding SessionSandboxBinding,
) (bool, error) {
if err := binding.Validate(key); err != nil {
return false, err
}
raw, err := json.Marshal(binding)
if err != nil {
return false, fmt.Errorf("encode sandbox binding: %w", err)
}
created, err := s.client.SetNX(ctx, s.bindingKey(key), raw, 0).Result()
if err != nil {
return false, fmt.Errorf("create sandbox binding: %w", err)
}
return created, nil
}
// DeleteIfMatch atomically deletes only the expected provider and sandbox ID.
func (s *RedisSessionSandboxBindingStore) DeleteIfMatch(
ctx context.Context,
key SessionSandboxKey,
provider RemoteProvider,
sandboxID string,
) (bool, error) {
if err := validateBindingMatch(key, provider, sandboxID); err != nil {
return false, err
}
deleted, err := deleteBindingIfMatchScript.Run(
ctx,
s.client,
[]string{s.bindingKey(key)},View on GitHub (pinned to 988cbb0330)
Solutions
- Check Redis connectivity: redis-cli -h <host> -p <port> ping from the app host and verify REDIS_* env vars
- Retry Create — the operation is idempotent thanks to SET NX semantics (returns created=false if already present)
- Check redis-server logs for READONLY/maxmemory/ACL errors and fix the server-side condition
- Increase the request context timeout and go-redis pool settings (PoolSize, dial/read/write timeouts) if errors correlate with load
Example fix
// before
created, err := store.Create(ctx, key, binding)
if err != nil { return err }
// after: bounded retry for transient Redis failures
var created bool
for attempt := 0; attempt < 3; attempt++ {
created, err = store.Create(ctx, key, binding)
if err == nil { break }
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(time.Duration(1<<attempt) * 100 * time.Millisecond):
}
}
if err != nil { return fmt.Errorf("create binding after retries: %w", err) }
if !created { /* binding already exists — proceed or fail per business rule */ } Defensive patterns
Strategy: retry
Validate before calling
// verify Redis is reachable before critical write paths
if err := rdb.Ping(ctx).Err(); err != nil {
return fmt.Errorf("redis unavailable before create: %w", err)
} Type guard
func isTransientRedisError(err error) bool {
if err == nil { return false }
return errors.Is(err, context.DeadlineExceeded) ||
errors.Is(err, context.Canceled) == false &&
(errors.Is(err, io.EOF) || errors.Is(err, syscall.ECONNRESET) ||
strings.Contains(err.Error(), "connection refused") ||
strings.Contains(err.Error(), "pool timeout"))
} Try / catch
var created bool
var err error
for i := 0; i < 3; i++ {
if created, err = store.Create(ctx, key, binding); err == nil { break }
if !isTransientRedisError(err) { break }
select {
case <-ctx.Done(): return ctx.Err()
case <-time.After(backoff(i)):
}
}
if err != nil { return err }
if !created { log.Printf("binding already existed for %s", key.SessionID) } Prevention
- Configure go-redis pool size and timeouts for your concurrency level
- Set up Redis health checks/readiness probes so traffic stops when Redis is down
- Use stable Redis credentials and rotate with zero-downtime (dual-user window)
- Prefer maxmemory-policy noeviction + capacity alerts over silent eviction of bindings
When it happens
Trigger: Calling Create(ctx, key, binding) when: Redis is down or restarting; network partition between app and Redis; ctx deadline exceeded while waiting for SetNX; writing to a read-only replica; Redis at maxmemory with no eviction policy; auth (ACL/password) misconfigured.
Common situations: Redis container restarted during a deploy; wrong REDIS_HOST/PORT or password in env; failover in progress on a sentinel/cluster setup; connection pool exhausted under load; ops applied 'replica-read-only yes' incorrectly to the primary.
Related errors
- get sandbox binding: %w
- delete sandbox binding: %w
- scan sandbox bindings: %w
- WEKNORA_REDIS_NAMESPACE must not contain braces
- WEKNORA_REDIS_NAMESPACE must not contain control characters
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/370abb49ede1cab2.
Report an issue: GitHub.