Tencent/WeKnora · error
sandbox binding version must be %d, got %d
Error message
sandbox binding version must be %d, got %d
What it means
SessionSandboxBinding.Validate enforces that a persisted binding was written with the current SessionSandboxBindingVersion schema. If b.Version differs (older rows from a previous release, or corrupted data) it returns this formatted mismatch error naming the expected and actual versions. Callers like BeginTurn/EndTurn/Get depend on it to reject stale bindings early.
Source
Thrown at internal/sandbox/session_binding.go:70
//
// Bindings written before this field existed carry an empty value. They are
// deliberately still valid — refusing them would break every live session
// on upgrade — and simply match no config until they are rebuilt.
ConfigID string `json:"config_id,omitempty"`
// StaleAt marks a binding whose sandbox boots an image the config has
// since replaced. The sandbox keeps serving until the session's next
// resolve, which destroys and recreates it; see InvalidateByConfig.
StaleAt *time.Time `json:"stale_at,omitempty"`
}
// Validate checks a binding against the current schema and authoritative key.
func (b SessionSandboxBinding) Validate(key SessionSandboxKey) error {
if err := key.Validate(); err != nil {
return err
}
if b.Version != SessionSandboxBindingVersion {
return fmt.Errorf(
"sandbox binding version must be %d, got %d",
SessionSandboxBindingVersion,
b.Version,
)
}
if !isRemoteProvider(b.Provider) {
return fmt.Errorf("unsupported sandbox binding provider %q", b.Provider)
}
if b.TenantID != key.TenantID || b.SessionID != key.SessionID {
return errors.New("sandbox binding identity does not match its key")
}
if strings.TrimSpace(b.SandboxID) == "" {
return errors.New("sandbox binding requires sandbox ID")
}
if strings.TrimSpace(b.TemplateID) == "" {
return errors.New("sandbox binding requires template ID")
}
if b.CreatedAt.IsZero() {View on GitHub (pinned to 988cbb0330)
Solutions
- Run the library's binding data migration or rewrite stored bindings to the current SessionSandboxBindingVersion
- Delete/invalidate stale bindings so they are recreated on the next BeginTurn
- Ensure all service instances run the same library version during rollouts
- Set Version: SessionSandboxBindingVersion explicitly when constructing bindings in tests
Example fix
// before
b := sandbox.SessionSandboxBinding{Provider: "docker", SandboxID: "sbx1"}
// after
b := sandbox.SessionSandboxBinding{
Provider: "docker", SandboxID: "sbx1",
Version: sandbox.SessionSandboxBindingVersion,
} Defensive patterns
Strategy: type-guard
Validate before calling
if b.Version != sandbox.SessionSandboxBindingVersion {
return migrateOrRecreateBinding(b)
} Type guard
func bindingCurrent(b sandbox.SessionSandboxBinding) bool {
return b.Version == sandbox.SessionSandboxBindingVersion
} Try / catch
if err := b.Validate(key); err != nil {
var verr *fmt.Errorf
if errors.As(err, &verr) && strings.Contains(err.Error(), "version must be") {
return recreateBinding(ctx, key) // drop stale-schema binding
}
return err
} Prevention
- Always set Version from the exported constant, never a literal
- Run data migrations before deploying schema-version bumps
- Keep library versions consistent across all instances
When it happens
Trigger: Loading a binding from storage (via Get or during BeginTurn/EndTurn) that was written by an older library version with a different binding schema version, or a binding struct populated by hand with a wrong Version field.
Common situations: Rolling deploy where old-version bindings persist in Redis while the new binary validates them; hand-crafted test fixtures with Version left at zero value; data migrations not run.
Related errors
- decode extract_result array: %w
- decode extract_result object: %w
- failed to decode API response: %w
- unsupported sandbox binding provider %q
- model ID cannot be empty
AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02).
Data as JSON: /api/errors/5b7633504c2a102c.
Report an issue: GitHub.