Skip to content

fix(clone): nil pointer dereference in PubSub after WithTimeout()#3710

Merged
ndyakov merged 4 commits into
masterfrom
copilot/fix-nil-pointer-panic
Feb 16, 2026
Merged

fix(clone): nil pointer dereference in PubSub after WithTimeout()#3710
ndyakov merged 4 commits into
masterfrom
copilot/fix-nil-pointer-panic

Conversation

Copilot AI commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

WithTimeout() clones the client but the clone() method omitted pubSubPool, causing nil pointer panics when using PubSub operations on the cloned client.

Changes:

  • Added pubSubPool field assignment in baseClient.clone()
  • Added test verifying PubSub works after WithTimeout()

Example:

rdb := redis.NewClient(&redis.Options{Addr: "localhost:6379"})
newRdb := rdb.WithTimeout(time.Second)

// Previously panicked with nil pointer dereference
// Now works correctly
pubsub := newRdb.Subscribe(ctx, "channel")
Original prompt

This section details on the original issue you should resolve

<issue_title>redis.WithTimeout() causes pubSubPool nil pointer dereference panic</issue_title>
<issue_description>## Simple:

newRdb.SubscribeHandler() reports "panic: nil pointer" after newRdb := redis.WithTimeout()
Because pubSubPool is not cloned


Sorry, English is not my native language, I wrote the details using AI.

Expected Behavior

A new Redis client instance created via WithTimeout() should retain the pubSubPool from the original client, allowing Pub/Sub operations (e.g., SubscribeHandler) to execute without memory errors.

Current Behavior

After calling WithTimeout() to clone a Redis client, using the new client for Pub/Sub operations triggers a nil pointer dereference panic. The error stack trace points to the pubSubPool field being nil in the cloned client:

panic: runtime error: invalid memory address or nil pointer dereference
go/pkg/mod/github.com/redis/go-redis/v9@v9.17.2/internal/pool/pubsub.go:37 +0x69

Root cause: The clone() method of baseClient does not copy the pubSubPool field to the new client instance.

Possible Solution

Modify the (c *baseClient) clone() *baseClient method in redis.go to explicitly clone the pubSubPool field from the original client to the new cloned instance.

Steps to Reproduce

  1. Initialize a base Redis client: rdb := redis.NewClient(...)
  2. Clone the client with a custom timeout: newRdb := rdb.WithTimeout(time.Second)
  3. Invoke Pub/Sub functionality on the cloned client: newRdb.SubscribeHandler(ctx, channel, handler)
  4. The program panics with the nil pointer dereference error mentioned above.

Context (Environment)

  • Affected Version: github.com/redis/go-redis/v9 v9.17.2
  • Problem Introduction: The issue emerged after the commit https://github.com/redis/go-redis/commit/0ef6d0727d6a452b0ea6eeee6bef3a72d35495ba#diff-190fc9ceda3bbdbe723d493b8b99e2b9a0100c7d635bfe9b04246280bef6f67e
  • Impact: Breaks Pub/Sub functionality for clients cloned via WithTimeout(), blocking related message subscription/publishing workflows.

Detailed Description

The baseClient struct in go-redis/v9 includes a pubSubPool field responsible for managing Pub/Sub connections. The WithTimeout() method relies on the clone() method to create a new client instance with updated timeout settings. However, the current implementation of clone() omits the pubSubPool field, leaving it as nil in the cloned client. When the cloned client attempts to perform Pub/Sub operations, it accesses the uninitialized pubSubPool, resulting in the nil pointer panic.

Possible Implementation

Update the clone() method of baseClient in redis.go to include the pubSubPool field during cloning:

func (c *baseClient) clone() *baseClient {
	c.maintNotificationsManagerLock.RLock()
	maintNotificationsManager := c.maintNotificationsManager
	c.maintNotificationsManagerLock.RUnlock()

	clone := &baseClient{
		opt:                         c.opt,
		connPool:                    c.connPool,
		onClose:                     c.onClose,
		pubSubPool:               c.pubSubPool, // Add this line to clone pubSubPool

		pushProcessor:               c.pushProcessor,
		maintNotificationsManager:   maintNotificationsManager,
		streamingCredentialsManager: c.streamingCredentialsManager,
	}
	return clone
    
}

This change ensures the cloned client inherits the pubSubPool from the original client, eliminating the nil pointer dereference error.</issue_description>

Comments on the Issue (you are @copilot in this section)

@ndyakov Hello @aeroplane , thank you for reporting this, we are going to look into it shortly.

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits February 13, 2026 10:25
Co-authored-by: ndyakov <1547186+ndyakov@users.noreply.github.com>
Co-authored-by: ndyakov <1547186+ndyakov@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix nil pointer dereference panic in redis.WithTimeout() Fix nil pointer dereference in PubSub after WithTimeout() Feb 13, 2026
Copilot AI requested a review from ndyakov February 13, 2026 10:33
@ndyakov ndyakov marked this pull request as ready for review February 13, 2026 16:10
@ndyakov ndyakov added the bug label Feb 13, 2026
@ndyakov ndyakov changed the title Fix nil pointer dereference in PubSub after WithTimeout() fix(clone): nil pointer dereference in PubSub after WithTimeout() Feb 13, 2026

@ndyakov ndyakov left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, this sets the pubsub pool correctly on clone

@ofekshenawa ofekshenawa left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@ndyakov ndyakov merged commit a881cd4 into master Feb 16, 2026
41 checks passed
@ndyakov ndyakov deleted the copilot/fix-nil-pointer-panic branch February 16, 2026 08:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

redis.WithTimeout() causes pubSubPool nil pointer dereference panic

3 participants