{"id":"21f88165819637a3","repo":"go-redis/redis","slug":"redis-reset-is-not-allowed-when-client-side-cachi","errorCode":null,"errorMessage":"redis: RESET is not allowed when client-side caching is enabled","messagePattern":"redis: RESET is not allowed when client-side caching is enabled","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"csc_integration.go","lineNumber":538,"sourceCode":"\n// errSelectWithCSC rejects runtime SELECT on clients with built-in CSC. Cache\n// keys use Options.DB, while SELECT mutates only the chosen pool connection.\nvar errSelectWithCSC = errors.New(\n\t\"redis: SELECT is not allowed when client-side caching is enabled\")\n\n// errAuthWithCSC rejects runtime authentication because it can change one\n// connection's ACL identity without changing the client's fixed cache namespace.\nvar errAuthWithCSC = errors.New(\n\t\"redis: AUTH is not allowed when client-side caching is enabled\")\n\n// errHelloWithCSC rejects HELLO with arguments because it can switch a tracked\n// connection out of RESP3 (and can also change authentication).\nvar errHelloWithCSC = errors.New(\n\t\"redis: HELLO with arguments is not allowed when client-side caching is enabled\")\n\n// errResetWithCSC rejects RESET because it disables tracking and switches the\n// connection to RESP2.\nvar errResetWithCSC = errors.New(\n\t\"redis: RESET is not allowed when client-side caching is enabled\")\n\n// errSubscribeWithCSC rejects raw subscriptions on the ordinary pool. The\n// typed Subscribe methods use dedicated PubSub connections and remain allowed.\nvar errSubscribeWithCSC = errors.New(\n\t\"redis: SUBSCRIBE is not allowed on pooled connections when client-side caching is enabled\")\n\n// cscCommandError rejects commands that can make a pooled connection's state\n// diverge from the assumptions used by CSC.\nfunc (c *baseClient) cscCommandError(cmd Cmder) error {\n\t// The successful attachment signal is shared with derived clients.\n\t// initConn's internal command wrapper is exempt during library setup.\n\tif !c.cscTrackingRequested() || c.allowClientTracking {\n\t\treturn nil\n\t}\n\tswitch {\n\tcase isClientTrackingCmd(cmd):\n\t\treturn errClientTrackingWithCSC","sourceCodeStart":520,"sourceCodeEnd":556,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/csc_integration.go#L520-L556","documentation":"Returned when a client built-in client-side caching (CSC) is enabled and a RESET command is issued on a pooled connection. RESET tears down the connection's tracking state and downgrades it to RESP2, which would silently invalidate the CSC assumptions the client relies on (cache keys are namespaced per RESP3-tracked connection). The guard in baseClient.cscCommandError matches RESET by its leading args, so even raw Do(ctx,\"RESET\",...) and pipelines are rejected.","triggerScenarios":"Calling client.Do(ctx, \"RESET\") or sending RESET through a pipeline on a *Client/*ClusterClient whose Options.ClientSideCache is non-nil. Also triggered by any Cmder whose first arg resolves to \"reset\" via cscCommandError -> isResetCmd.","commonSituations":"Borrowing a RESET call from another client library's recipe, health-check liveness probes that issue RESET, or migrating code to a CSC-enabled client without dropping the RESET handshake.","solutions":["Remove the RESET call; go-redis manages connection lifecycle internally — use client.Close() and create a fresh client if you need a clean connection.","If you must reset, disable built-in CSC by leaving Options.ClientSideCache nil and manage CLIENT TRACKING yourself.","For connection-level health checks use client.Ping(ctx) instead of RESET."],"exampleFix":"// before\nclient.Do(ctx, \"RESET\")\n// after\nclient.Close()\nclient = redis.NewClient(opts)","handlingStrategy":"validation","validationCode":"// Don't issue RESET on a CSC-enabled client at all.\n// If you must, verify CSC is off first (either field enables it):\nopts := client.Options()\nif opts.ClientSideCache == nil && opts.ClientSideCacheConfig == nil {\n    client.Do(ctx, \"RESET\")\n}","typeGuard":"func isCSCEnabled(c *redis.Client) bool {\n    o := c.Options()\n    return o.ClientSideCache != nil || o.ClientSideCacheConfig != nil\n}","tryCatchPattern":"err := client.Do(ctx, \"RESET\").Err()\nif err != nil && strings.Contains(err.Error(), \"RESET is not allowed\") {\n    // drop RESET; use Close()+recreate instead\n    client.Close()\n}","preventionTips":["Avoid issuing RESET, CLIENT TRACKING, SELECT, AUTH, HELLO-with-args, and raw SUBSCRIBE on CSC-enabled clients.","Use the typed pubsub API and let the client own connection state.","Drive liveness checks through Ping, not RESET."],"tags":["csc","client-side-caching","resp3","command-guard"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}