Tencent/WeKnora · error
consume sandbox turn rebuild: %w
Error message
consume sandbox turn rebuild: %w
What it means
ConsumeTurnRebuild runs a Lua script that atomically spends the single stale-sandbox rebuild allowed for the current turn in the Redis turn-lease hash. This error wraps any failure of that script execution (connection error, script error, NOSCRIPT, context cancellation). It is thrown because silently skipping consumption could let a later mid-turn install tear down a sandbox that in-flight work depends on.
Source
Thrown at internal/sandbox/session_binding_redis.go:375
refs, _ := strconv.Atoi(values["refs"])
if refs <= 0 {
return false, false, nil
}
return true, values["rebuild"] == "1", nil
}
// ConsumeTurnRebuild spends the one rebuild allowed for the current turn.
func (s *RedisSessionSandboxBindingStore) ConsumeTurnRebuild(
ctx context.Context,
key SessionSandboxKey,
) error {
if err := key.Validate(); err != nil {
return err
}
if err := consumeTurnRebuildScript.Run(
ctx, s.client, []string{s.turnKey(key)}, sessionTurnLeaseTTL.Milliseconds(),
).Err(); err != nil {
return fmt.Errorf("consume sandbox turn rebuild: %w", err)
}
return nil
}
func (s *RedisSessionSandboxBindingStore) turnKey(key SessionSandboxKey) string {
return "weknora:sandbox:session:{" + s.hashTag(key) + "}:turn"
}
func (s *RedisSessionSandboxBindingStore) bindingKey(key SessionSandboxKey) string {
return "weknora:sandbox:session:{" + s.hashTag(key) + "}:binding"
}
func (s *RedisSessionSandboxBindingStore) lockKey(key SessionSandboxKey) string {
// Keep the historical suffix used by the saved multi-node Cube
// implementation so rolling upgrades serialize on the same lock.
return "weknora:sandbox:session:{" + s.hashTag(key) + "}:create-lock"
}
View on GitHub (pinned to 988cbb0330)
Solutions
- Verify Redis availability and connectivity; fix connection/auth config.
- Unwrap the error chain: if it is a retryable Redis I/O error, retry the operation — consuming the rebuild is idempotent in effect per turn.
- Check Redis memory (maxmemory) if OOM errors are wrapped, and raise limits or enable eviction policy appropriate for these keys.
- Ensure all WeKnora nodes load the same script version (matching deployments) to avoid persistent script mismatches.
Example fix
// before
if err := store.ConsumeTurnRebuild(ctx, key); err != nil {
return err
}
// after
if err := store.ConsumeTurnRebuild(ctx, key); err != nil {
if isRetryableRedisErr(err) { // e.g. io.EOF, net timeout, redis.Nil-free I/O errors
if retryErr := store.ConsumeTurnRebuild(ctx, key); retryErr != nil {
return fmt.Errorf("consume sandbox turn rebuild: %w", retryErr)
}
} else {
return err
}
} Defensive patterns
Strategy: retry
Validate before calling
if err := rdb.Ping(ctx).Err(); err != nil {
return fmt.Errorf("redis unavailable before ConsumeTurnRebuild: %w", err)
} Type guard
func isRetryableRedisErr(err error) bool {
var rerr *redis.RedisError
return errors.As(err, &rerr) && !strings.Contains(err.Error(), "NOSCRIPT")
} Try / catch
if err := store.ConsumeTurnRebuild(ctx, key); err != nil {
if isRetryableRedisErr(err) {
err = store.ConsumeTurnRebuild(ctx, key)
}
if err != nil { return fmt.Errorf("consume rebuild: %w", err) }
} Prevention
- Deploy all nodes with matching script versions to avoid NOSCRIPT drift.
- Keep Redis memory headroom so writes (rebuild flag consumption) never OOM.
- Wrap turn-boundary work in a context with enough budget for Redis round trips.
- Alert on Redis write failures during resolve paths.
When it happens
Trigger: RedisSessionSandboxBindingStore.ConsumeTurnRebuild is called (from resolveLocked after stale handling) when Redis is down, the EVALSHA/EVAL call fails, the script returns an error, or ctx is cancelled during the round trip.
Common situations: Redis failover mid-request; Redis SCRIPT FLUSH causing transient NOSCRIPT (usually auto-retried by go-redis, but surfaces if retries are disabled); network blips; Redis OOM refusing writes.
Related errors
- read sandbox turn lease: %w
- WEKNORA_REDIS_NAMESPACE must not contain braces
- WEKNORA_REDIS_NAMESPACE must not contain control characters
- delete sandbox binding: %w
- mark sandbox binding stale: %w
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/fdfe57c291cd6294.
Report an issue: GitHub.