Skip to content

AttributeError: module 'redis' has no attribute 'client' #34227

Open

Description

@thorfi

Describe the bug

After doing:

brew uninstall --formula azure-cli
brew install azure-cli

To migrate to the Cask version of az, the following error is appearing on any az commands:

% az login
The command failed with an unexpected error. Here is the traceback:
module 'redis' has no attribute 'client'
...
AttributeError: module 'redis' has no attribute 'client'

Related command

az login

Errors

% az login
The command failed with an unexpected error. Here is the traceback:
module 'redis' has no attribute 'client'
Traceback (most recent call last):
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/knack/cli.py", line 233, in invoke
    cmd_result = self.invocation.execute(args)
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/azure/cli/core/commands/__init__.py", line 677, in execute
    raise ex
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/azure/cli/core/commands/__init__.py", line 820, in _run_jobs_serially
    results.append(self._run_job(expanded_arg, cmd_copy))
                   ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/azure/cli/core/commands/__init__.py", line 789, in _run_job
    result = cmd_copy(params)
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/azure/cli/core/commands/__init__.py", line 335, in __call__
    return self.handler(*args, **kwargs)
           ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/azure/cli/core/commands/command_operation.py", line 120, in handler
    return op(**command_args)
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/azure/cli/command_modules/profile/custom.py", line 215, in login
    subscriptions = profile.login(
        interactive,
    ...<11 lines>...
        subscription=subscription
    )
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/azure/cli/core/_profile.py", line 164, in login
    identity = _create_identity_instance(self.cli_ctx, self._authority, tenant_id=tenant)
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/azure/cli/core/_profile.py", line 969, in _create_identity_instance
    from .auth.identity import Identity
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/azure/cli/core/auth/identity.py", line 18, in <module>
    from .persistence import load_persisted_token_cache, file_extensions, load_secret_store
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/azure/cli/core/auth/persistence.py", line 12, in <module>
    from msal_extensions import (FilePersistenceWithDataProtection, KeychainPersistence, LibsecretPersistence,
                                 FilePersistence, PersistedTokenCache, CrossPlatLock)
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/msal_extensions/__init__.py", line 11, in <module>
    from .token_cache import PersistedTokenCache, CrossPlatLock, LockError
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/msal_extensions/token_cache.py", line 9, in <module>
    from .cache_lock import (  # pylint: disable=unused-import
    ...<2 lines>...
        )
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/msal_extensions/cache_lock.py", line 8, in <module>
    import portalocker  # pylint: disable=import-error
    ^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/portalocker/__init__.py", line 11, in <module>
    from .redis import RedisLock
  File "/opt/homebrew/Caskroom/azure-cli/2.91.0/libexec/lib/python3.14/site-packages/portalocker/redis.py", line 21, in <module>
    class PubSubWorkerThread(redis.client.PubSubWorkerThread):
                             ^^^^^^^^^^^^
AttributeError: module 'redis' has no attribute 'client'

Issue script & Debug output

Any az command.

Expected behavior

az cli should work, not crash

Environment Summary

azure-cli 2.91.0

core 2.91.0
telemetry 1.1.0

Extensions:
account 0.2.5
application-insights 2.0.0b2
containerapp 1.3.0b5
costmanagement 1.0.0
log-analytics 1.0.0b3
log-analytics-solution 1.0.1
logic 1.1.0
portal 1.0.0b2
quota 1.0.0
redisenterprise 1.5.0b1
storagesync 1.0.1

Dependencies:
msal 1.39.0
azure-mgmt-resource 24.0.0

Python location '/opt/homebrew/opt/python@3.14/bin/python3.14'
Config directory '/Users/thorfinn/.azure'
Extensions directory '/Users/thorfinn/.azure/cliextensions'

Python (Darwin) 3.14.8 (main, Sep 30 2026, 17:55:09) [Clang 21.0.0 (clang-2100.3.34.2)]

Legal docs and information: aka.ms/AzureCliLegal

Your CLI is up-to-date.

Additional context

No response

Activity

  1. added
    bugThis issue requires a change to an existing behavior in the product in order to be resolved.
    on Oct 15, 2026
  2. added
    customer-reportedIssues that are reported by GitHub users external to the Azure organization.
    Accountaz login/account
    Azure CLI TeamThe command of the issue is owned by Azure CLI team
    questionThe issue doesn't require a change to the product in order to be resolved. Most issues start as that
    on Oct 15, 2026
  3. yonzhan commented on Oct 15, 2026

    @yonzhan
    Collaborator

    Thank you for opening this issue, we will look into it.

  4. removed
    questionThe issue doesn't require a change to the product in order to be resolved. Most issues start as that
    on Oct 15, 2026
  5. added this to the Backlog milestone on Oct 15, 2026
  6. thorfi commented on Oct 15, 2026

    @thorfi
    Author

    Yong Zhang (@yonzhan) - thanks, right now I can't use the az cli at all, so this is a big problem. I tried removing my $HOME/.azure* directories just in case, but that didn't change anything.

  7. x-engineering-agent commented on Oct 15, 2026

    @x-engineering-agent
    Contributor

    @thorfi (@thorfi), the version, migration steps and traceback already identify the failure: az login crashes while importing msal_extensions → portalocker → redis.client, before sign-in or token-cache access. This is the Python redis import, not the azure-mgmt-redis management SDK. The reported invocation also goes through bin/gitenv.sh, so we cannot yet distinguish a Cask dependency problem from that wrapper's Python import environment.

    Does az login reproduce the same redis.client error when invoked directly from a fresh terminal outside the project directory, without bin/gitenv.sh? Please share that result, removing any tokens or personal details. That single control will determine whether to investigate the Cask's installed dependencies or the wrapper's import environment; your reply will automatically resume triage.

    Posted by x-engineering-agent (Fixer)

  8. microsoft-github-policy-service commented on Oct 15, 2026

    @microsoft-github-policy-service
    Contributor

    🔔 Routing this issue to @Azure/act-identity-squad.

  9. 32 remaining items

  10. x-engineering-agent commented on Oct 20, 2026

    @x-engineering-agent
    Contributor

    X Engineering Agent Bug analysis: Root cause analysis

    Below is my analysis of this issue:

    Summary

    The reported az login fails during auth dependency imports in a project directory containing an empty redis folder. The reporter also observed the error in the CLI container and says Python safe-path mode avoids it. An isolated sandbox reproduced the same error on the dev build using az group list from that directory; reported/latest 2.91.0 release environments passed the same steps, so the release packaging difference is not established.

    🔬 Likely root cause

    The launcher runs Python with -m azure.cli without excluding the implicit working-directory import entry, and CLI startup imports core dependencies without removing that entry. A local empty redis folder can shadow the installed redis package when portalocker imports it through msal_extensions during auth initialization; the shadow module lacks client and stops the command before token handling. This path is reproduced on the dev sandbox, not yet established across all release launchers.

    Affected code
    • src/azure-cli/azure/cli/__main__.py › cli_main (line 26)
    • src/azure-cli-core/azure/cli/core/_profile.py › _create_identity_instance (line 967)
    • src/azure-cli-core/azure/cli/core/auth/persistence.py › load_persisted_token_cache (line 26)
    🚫 Ruled out
    • Configuration: Removing local Azure configuration did not resolve the reported failure. The traceback fails at dependency import before cache use; this is not caused by account settings.
    • Environment: Homebrew migration alone is insufficient: the reporter saw it in the container and an isolated dev sandbox reproduced it with an empty redis folder. CWD is the trigger; any release-launcher differences remain unverified.
    • Intended behavior: Python -m intentionally exposes the working directory, but an unrelated project folder must not break Azure CLI auth. Explicit extension and PYTHONPATH imports should be preserved.
    🛠️ Proposed change

    In src/azure-cli/azure/cli/main.py, remove only the implicit unsafe CWD sys.path entry before third-party imports, compatibly with Python 3.10 and newer; audit owned -m launchers including src/azure-cli/az, az.bat, azps.ps1 and scripts/curl_install_pypi/install.py so interpreter startup cannot reintroduce it. Preserve explicit extension paths and investigate Cask packaging separately.

    Workaround

    The reporter says setting PYTHONSAFEPATH=1 avoids the error in their environment; leaving the directory with the shadowing redis folder also avoids it.

    🔬 Technical details

    Evidence

    • src/azure-cli/az:19 executes python -m azure.cli; src/azure-cli/azure/cli/main.py imports core without filtering sys.path.
    • src/azure-cli-core/azure/cli/core/_profile.py:967-969 lazily imports Identity; auth/persistence.py:12 imports msal_extensions. The reporter and sandbox tracebacks continue through portalocker to redis.client.PubSubWorkerThread.
    • Sandbox run 39347404670 ran az group list with an empty redis working-directory entry: dev at ce030fb matched the AttributeError; reported/latest 2.91.0 builds exited successfully under the same spec.

    Test plan

    Add a subprocess regression exercising the real auth command/import path from a directory with an empty redis folder, not just a unit test of sys.path. Cover a packaged or owned launcher and python -m entry, and confirm explicit extension imports still work. Rerun the original isolated az group list ReproSpec against the resulting PR head; check the Cask/container launchers when available.

    Generated code: Handwritten code. azure/cli/main.py and azure-cli-core/auth/persistence.py are handwritten source files, not aaz or AutoRest-generated clients.

    🔁 Live reproduction (BAMI sandbox) — Reproduced

    Verdict: Reproduced on the current build.

    Version Result Evidence
    2.91.0 (reported) Not reproduced exit 0
    2.91.0 (latest) Not reproduced exit 0
    dev @ ce030fb Reproduced exit 1
    Steps run (redacted)

    2.91.0 (reported)

    repro: az group list -> exit 0
    

    2.91.0 (latest)

    repro: az group list -> exit 0
    

    dev @ ce030fb

    repro: az group list -> exit 1, matches the issue
    

    Sandbox run

    Commands ran in an isolated Azure sandbox subscription from a validated ReproSpec; output is redacted.

    X Engineering Agent · Fixer · react 👍 / 👎 to train the agent

  11. a0x1ab commented on Oct 20, 2026

    @a0x1ab
    Member

    Apologies for the issues @thorfi (@thorfi) and Yeming Liu (@isra-fel), the X Engineering Agent faced issues as our internal testing tenant was down. This has now been fixed. Please see above for the updated bug analysis, as I have also improved the agent's capabilities. It has correctly identified and reproduced the bug as expected:

    Image
  12. rolf-bv commented on Oct 27, 2026

    @rolf-bv

    This is not only a crash. It is a security risk.

    A file named redis/init.py in the current directory executes when az starts, because the launcher runs python -sm azure.cli and -m adds the current directory to sys.path before anything else.

    Reproduce this by creating redis/__init__.py with contents:

    #!/usr/bin/env python
    import os
    import sys
    print("Hello", os.environ.get("USER"))
    print("Thank you for using Azure")
    sys.exit()

    Then run az aks list in the folder that has this new redis folder with redis/__init__py file in it.

    No need to set the execute bit on that __init__.py file, it will run fine without it and do whatever you want:

     19:43:35  ➜ az aks list
    The behavior of this command has been altered by the following extension: aks-preview
    Hello <USERNAME HERE>
    Thank you for using Azure

    A simple fix seems to be:

    sudo sed -i 's/-sm/-Psm/' /usr/bin/az

    This replaces $python_cmd -sm with $python_cmd -Psm

     ❯ python --help | grep "\-P"
    -I     : isolate Python from the user's environment (implies -E, -P and -s)
    -P     : don't prepend a potentially unsafe path to sys.path; also
    

    The risk is that az will happily run this anywhere and its very likely not limited to the aks subcommand

    This leads to unpredictable behaviour.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Auto-AssignAuto assign by botAzure CLI TeamThe command of the issue is owned by Azure CLI teamact-platform-engineering-squadbugThis issue requires a change to an existing behavior in the product in order to be resolved.customer-reportedIssues that are reported by GitHub users external to the Azure organization.

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions