Tencent/WeKnora · error

sandbox binding requires tenant and session

Error message

sandbox binding requires tenant and session

What it means

SessionSandboxKey.Validate requires a key to identify a tenant session: TenantID must be non-zero and SessionID must be non-blank. This error means one or both are missing, so the sandbox cannot be bound, looked up, or used for a turn (Get, WithLifecycleLock, BeginTurn, EndTurn all validate first).

Source

Thrown at internal/sandbox/session_binding.go:25

	"strings"
	"sync"
	"time"
	"unicode"
)

// SessionSandboxBindingVersion is the current persisted binding schema.
const SessionSandboxBindingVersion = 1

// SessionSandboxKey identifies one tenant-scoped persistent sandbox.
type SessionSandboxKey struct {
	TenantID  uint64
	SessionID string
}

// Validate rejects keys that cannot identify a tenant session.
func (k SessionSandboxKey) Validate() error {
	if k.TenantID == 0 || strings.TrimSpace(k.SessionID) == "" {
		return errors.New("sandbox binding requires tenant and session")
	}
	if strings.ContainsAny(k.SessionID, "{}") {
		return errors.New("sandbox binding session must not contain braces")
	}
	for _, r := range k.SessionID {
		if unicode.IsControl(r) {
			return errors.New("sandbox binding session must not contain control characters")
		}
	}
	return nil
}

// SessionSandboxBinding records the remote sandbox assigned to a session.
type SessionSandboxBinding struct {
	Version    int            `json:"version"`
	Provider   RemoteProvider `json:"provider,omitempty"`
	TenantID   uint64         `json:"tenant_id"`
	SessionID  string         `json:"session_id"`

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Populate TenantID with the authenticated tenant's ID before building the key.
  2. Trim and check the session ID at the API boundary and reject requests lacking it.
  3. Construct SessionSandboxKey only after tenant and session resolution succeeds, then call Validate early to fail fast.

Example fix

// before
key := sandbox.SessionSandboxKey{SessionID: sessionID} // TenantID missing
err := key.Validate() // "sandbox binding requires tenant and session"
// after
key := sandbox.SessionSandboxKey{TenantID: tenantID, SessionID: strings.TrimSpace(sessionID)}
err := key.Validate()
Defensive patterns

Strategy: validation

Validate before calling

func keyReady(tenantID int64, sessionID string) error {
    if tenantID == 0 { return errors.New("tenant id required") }
    if strings.TrimSpace(sessionID) == "" { return errors.New("session id required") }
    return nil
}

Type guard

func validSessionKey(k sandbox.SessionSandboxKey) bool {
    return k.TenantID != 0 && strings.TrimSpace(k.SessionID) != ""
}

Try / catch

if err := key.Validate(); err != nil {
    return fmt.Errorf("bad session sandbox key (tenant=%d session=%q): %w", key.TenantID, key.SessionID, err)
}

Prevention

When it happens

Trigger: Calling Get/BeginTurn/EndTurn/WithLifecycleLock with a SessionSandboxKey where TenantID == 0, or SessionID is empty/whitespace only.

Common situations: Building the key before the auth/session context is resolved so TenantID is still the zero value; a request missing the session identifier; an unset struct field after a refactor.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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