Tencent/WeKnora · error

validate sandbox binding: %w

Error message

validate sandbox binding: %w

What it means

Returned by RedisSessionSandboxBindingStore.Get when the stored binding decoded successfully as JSON but failed binding.Validate(key) — the SessionSandboxBinding content does not match expectations: missing/empty provider or sandbox ID, or the binding belongs to a different tenant/session than the requested key. This guards against malformed but parseable records. The error is wrapped as 'validate sandbox binding: %w'.

Source

Thrown at internal/sandbox/session_binding_redis.go:130

	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,
) (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)
	}

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Log the stored value (redis-cli GET the binding key) and check which Validate rule fails: empty provider, empty sandbox ID, or tenant/session mismatch
  2. Delete the invalid binding with DEL or store.DeleteIfMatch so the session is treated as unbound and a fresh binding is created on next resolve
  3. Verify WEKNORA_REDIS_NAMESPACE matches across environments — a shared namespace lets bindings from one deployment validate against another tenant's keys
  4. Roll forward all instances to the same schema version so validators and writers agree on required fields

Example fix

// before
binding, err := store.Get(ctx, key)
if err != nil { return fmt.Errorf("resolve: %w", err) }
// after: rebuild the binding when the stored one fails validation
binding, err := store.Get(ctx, key)
if err != nil {
    if strings.Contains(err.Error(), "validate sandbox binding") {
        if derr := store.DeleteIfMatch(ctx, key, lastKnown.Provider, lastKnown.SandboxID); derr != nil {
            return derr
        }
        if _, cerr := store.Create(ctx, key, lastKnown); cerr != nil {
            return cerr
        }
        binding, err = store.Get(ctx, key)
        if err != nil { return err }
    } else {
        return fmt.Errorf("resolve: %w", err)
    }
}
Defensive patterns

Strategy: validation

Validate before calling

// validate the fetched binding yourself before trusting it
func bindingUsable(b *sandbox.SessionSandboxBinding, key sandbox.SessionSandboxKey) bool {
    return b != nil && b.Provider != "" && b.SandboxID != "" && b.Validate(key) == nil
}

Type guard

func isValidateBindingError(err error) bool {
    return err != nil && strings.Contains(err.Error(), "validate sandbox binding")
}

Try / catch

binding, err := store.Get(ctx, key)
switch {
case isValidateBindingError(err):
    log.Printf("invalid binding for session %s: %v — recreating", key.SessionID, err)
    _ = store.DeleteIfMatch(ctx, key, provider, sandboxID)
    _, _ = store.Create(ctx, key, newBinding)
binding, err = store.Get(ctx, key)

Prevention

When it happens

Trigger: Calling Get(ctx, key) when the stored binding has an empty Provider or SandboxID, references a mismatched TenantID/SessionID relative to the key, or is otherwise in an invalid state per SessionSandboxBinding.Validate (e.g. a stale write from a failed partial update).

Common situations: Data written by an older version with fewer required fields; a binding JSON that was hand-crafted or restored from a backup of another environment; cross-tenant key collision after a namespace misconfiguration; a partial write during a failed migration.

Related errors


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