{"record":{"id":"02a8e09d302c281b","repo":"Tencent/WeKnora","slug":"validate-sandbox-binding-w","errorCode":null,"errorMessage":"validate sandbox binding: %w","messagePattern":"validate sandbox binding: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sandbox/session_binding_redis.go","lineNumber":130,"sourceCode":"\tkey SessionSandboxKey,\n) (*SessionSandboxBinding, error) {\n\tif err := key.Validate(); err != nil {\n\t\treturn nil, err\n\t}\n\traw, err := s.client.Get(ctx, s.bindingKey(key)).Bytes()\n\tif errors.Is(err, redis.Nil) {\n\t\treturn nil, nil\n\t}\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get sandbox binding: %w\", err)\n\t}\n\n\tvar binding SessionSandboxBinding\n\tif err := json.Unmarshal(raw, &binding); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode sandbox binding: %w\", err)\n\t}\n\tif err := binding.Validate(key); err != nil {\n\t\treturn nil, fmt.Errorf(\"validate sandbox binding: %w\", err)\n\t}\n\treturn &binding, nil\n}\n\n// Create stores a validated current-schema binding with SET NX and no\n// expiration.\nfunc (s *RedisSessionSandboxBindingStore) Create(\n\tctx context.Context,\n\tkey SessionSandboxKey,\n\tbinding SessionSandboxBinding,\n) (bool, error) {\n\tif err := binding.Validate(key); err != nil {\n\t\treturn false, err\n\t}\n\traw, err := json.Marshal(binding)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"encode sandbox binding: %w\", err)\n\t}","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/sandbox/session_binding_redis.go#L112-L148","documentation":"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'.","triggerScenarios":"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).","commonSituations":"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.","solutions":["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","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","Verify WEKNORA_REDIS_NAMESPACE matches across environments — a shared namespace lets bindings from one deployment validate against another tenant's keys","Roll forward all instances to the same schema version so validators and writers agree on required fields"],"exampleFix":"// before\nbinding, err := store.Get(ctx, key)\nif err != nil { return fmt.Errorf(\"resolve: %w\", err) }\n// after: rebuild the binding when the stored one fails validation\nbinding, err := store.Get(ctx, key)\nif err != nil {\n    if strings.Contains(err.Error(), \"validate sandbox binding\") {\n        if derr := store.DeleteIfMatch(ctx, key, lastKnown.Provider, lastKnown.SandboxID); derr != nil {\n            return derr\n        }\n        if _, cerr := store.Create(ctx, key, lastKnown); cerr != nil {\n            return cerr\n        }\n        binding, err = store.Get(ctx, key)\n        if err != nil { return err }\n    } else {\n        return fmt.Errorf(\"resolve: %w\", err)\n    }\n}","handlingStrategy":"validation","validationCode":"// validate the fetched binding yourself before trusting it\nfunc bindingUsable(b *sandbox.SessionSandboxBinding, key sandbox.SessionSandboxKey) bool {\n    return b != nil && b.Provider != \"\" && b.SandboxID != \"\" && b.Validate(key) == nil\n}","typeGuard":"func isValidateBindingError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"validate sandbox binding\")\n}","tryCatchPattern":"binding, err := store.Get(ctx, key)\nswitch {\ncase isValidateBindingError(err):\n    log.Printf(\"invalid binding for session %s: %v — recreating\", key.SessionID, err)\n    _ = store.DeleteIfMatch(ctx, key, provider, sandboxID)\n    _, _ = store.Create(ctx, key, newBinding)\nbinding, err = store.Get(ctx, key)","preventionTips":["Enforce a single WEKNORA_REDIS_NAMESPACE per deployment so tenants never share binding keys","Only write bindings through store.Create, which validates before persisting","Pin all instances to the same app version during deploys to avoid schema skew","Restore Redis backups only into the environment that produced them"],"tags":["redis","validation","schema-mismatch","go"],"backgroundTag":"binding-validation-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}