{"record":{"id":"cc990fc340370424","repo":"redis/go-redis","slug":"redis-client-tracking-is-not-allowed-when-client","errorCode":null,"errorMessage":"redis: CLIENT TRACKING is not allowed when client-side caching is enabled","messagePattern":"redis: CLIENT TRACKING is not allowed when client-side caching is enabled","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"csc_integration.go","lineNumber":518,"sourceCode":"\t}\n\treturn 0\n}\n\n// cscForgetConn drops connID's init-generation entry when initialization does\n// not establish tracked coverage, either because init failed or tracking was\n// rejected and CSC was disabled.\nfunc (c *baseClient) cscForgetConn(connID uint64) {\n\tif h := c.cscHook(); h != nil {\n\t\th.forgetConn(connID)\n\t}\n}\n\n// errClientTrackingWithCSC rejects CLIENT TRACKING on clients with built-in CSC\n// (see the guards in baseClient.process and generalProcessPipeline). The raw\n// escape hatches — Do(ctx, \"client\", \"tracking\", ...) with string or []byte\n// args, and pipelines — are also caught: the guard matches on the command's\n// leading args, not the typed method.\nvar errClientTrackingWithCSC = errors.New(\n\t\"redis: CLIENT TRACKING is not allowed when client-side caching is enabled\")\n\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","sourceCodeStart":500,"sourceCodeEnd":536,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/csc_integration.go#L500-L536","documentation":"When the client's built-in client-side caching (CSC) is enabled, the library forbids issuing CLIENT TRACKING — including raw Do(ctx, \"client\", \"tracking\", ...) escapes and pipelines — because the two invalidation mechanisms conflict. The guard in baseClient.process and generalProcessPipeline matches on the command's leading args and returns errClientTrackingWithCSC.","triggerScenarios":"Calling rdb.ClientTracking(...) on a client whose Options enable built-in CSC; or bypassing the typed method with rdb.Do(ctx, \"client\", \"tracking\", \"optin\") or the same inside a pipeline on such a client.","commonSituations":"Migrating manual CLIENT TRACKING code to the built-in cache without removing the old tracking setup; enabling Options-level CSC while retaining middleware that issues CLIENT TRACKING at connect time.","solutions":["Remove the CLIENT TRACKING call — built-in CSC manages tracking itself.","Disable built-in CSC in the client Options if you must control CLIENT TRACKING manually.","Search for raw Do() calls with \"client\" \"tracking\" args and pipelines issuing them, and delete them."],"exampleFix":"// before\nrdb.Do(ctx, \"client\", \"tracking\", \"optin\") // CSC-enabled client\n// after\n// built-in CSC handles tracking; remove the manual command, or\n// disable built-in CSC in Options to manage tracking yourself","handlingStrategy":"validation","validationCode":"func clientTrackingAllowed(opts *redis.Options) bool {\n    return !clientSideCachingEnabled(opts) // remove manual CLIENT TRACKING when CSC is on\n}","typeGuard":null,"tryCatchPattern":"if err := rdb.ClientTracking(ctx, opt).Err(); err != nil {\n    if strings.Contains(err.Error(), \"not allowed when client-side caching is enabled\") {\n        // drop the manual tracking call; built-in CSC owns tracking\n    }\n}","preventionTips":["When enabling built-in CSC, audit and remove all manual CLIENT TRACKING code, including raw Do() and pipeline variants.","Grep for Do(ctx, \"client\", \"tracking\") in middleware/hooks.","Choose one invalidation strategy per client: built-in CSC or manual tracking."],"tags":["client-tracking","client-side-caching","conflict"],"backgroundTag":"client-tracking-csc-conflict","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}