{"record":{"id":"59d11951e0c94aba","repo":"Tencent/WeKnora","slug":"encode-sandbox-binding-w","errorCode":null,"errorMessage":"encode sandbox binding: %w","messagePattern":"encode sandbox binding: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sandbox/session_binding_redis.go","lineNumber":147,"sourceCode":"\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}\n\tcreated, err := s.client.SetNX(ctx, s.bindingKey(key), raw, 0).Result()\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"create sandbox binding: %w\", err)\n\t}\n\treturn created, nil\n}\n\n// DeleteIfMatch atomically deletes only the expected provider and sandbox ID.\nfunc (s *RedisSessionSandboxBindingStore) DeleteIfMatch(\n\tctx context.Context,\n\tkey SessionSandboxKey,\n\tprovider RemoteProvider,\n\tsandboxID string,\n) (bool, error) {\n\tif err := validateBindingMatch(key, provider, sandboxID); err != nil {\n\t\treturn false, err\n\t}","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/sandbox/session_binding_redis.go#L129-L165","documentation":"Returned by RedisSessionSandboxBindingStore.Create when json.Marshal of the SessionSandboxBinding fails before the SET NX is issued. Marshal of a plain struct rarely fails, so this almost always indicates the binding contains a value JSON cannot represent (e.g. a channel, func, or cyclic value added to the struct) or a custom MarshalJSON that errors. Wrapped as 'encode sandbox binding: %w'.","triggerScenarios":"Calling Create(ctx, key, binding) where the binding (or a nested field added to SessionSandboxBinding) contains an unsupported type — channels, funcs, cycles — or implements MarshalJSON returning an error.","commonSituations":"A developer extended SessionSandboxBinding with a non-serializable field (e.g. *time.Ticker, sync primitives, interface holding a channel); a custom MarshalJSON implementation panics/errors on zero values; struct embedding pulled in unserializable fields.","solutions":["Inspect the wrapped %w error — it names the unsupported type; remove or replace the non-serializable field on SessionSandboxBinding","Add a field with json:\"-\" if it is runtime-only and must not be persisted","Ensure any custom MarshalJSON handles zero/nil values gracefully","Unit-test Create with a fully populated binding to catch serialization regressions before deployment"],"exampleFix":"// before\ntype SessionSandboxBinding struct {\n    Provider  RemoteProvider\n    SandboxID string\n    Runtime   *SandboxRuntime // contains a channel: json.Marshal fails\n}\n// after\ntype SessionSandboxBinding struct {\n    Provider  RemoteProvider\n    SandboxID string\n    Runtime   *SandboxRuntime `json:\"-\"` // runtime-only, not persisted\n}","handlingStrategy":"validation","validationCode":"// fail fast in tests/CI when SessionSandboxBinding gains non-serializable fields\nfunc TestBindingIsJSONEncodable(t *testing.T) {\n    b := sandbox.SessionSandboxBinding{Provider: provider, SandboxID: \"sbx-123\"}\n    if _, err := json.Marshal(b); err != nil {\n        t.Fatalf(\"binding not encodable: %v\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"created, err := store.Create(ctx, key, binding)\nif err != nil && strings.Contains(err.Error(), \"encode sandbox binding\") {\n    return fmt.Errorf(\"programming error: binding type not serializable: %w\", err)\n}","preventionTips":["Keep SessionSandboxBinding limited to JSON-native field types (strings, *time.Time)","Mark runtime-only fields with json:\"-\"","Add a round-trip Marshal/Unmarshal unit test for the binding struct","Do not embed unexported types or interfaces holding channels/funcs in the struct"],"tags":["json-encode","go","serialization","redis"],"backgroundTag":"json-marshal-unsupported-type","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}