Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`Invoke-Conda` cannot catch any arguments after powershell 7.5.0 update

I upgraded my powershell from 7.4.6 to 7.5.0. Then I found that I could not activate any conda environments and conda cannot catch any arguments:

base 3.12.8  ➜ conda --version
usage: conda-script.py [-h] [-v] [--no-plugins] [-V] COMMAND ...
conda-script.py: error: argument COMMAND: invalid choice: '' (choose from activate, clean, commands, compare, config, create, deactivate, env, export, info, init, install, list, notices, package, content-trust, doctor, repoquery, remove, uninstall, rename, run, search, update, upgrade)

As usual, command conda redirects to Invoke-Conda defined in %USERPROFILE%\miniconda3\shell\condabin\Conda.psm1

 base 3.12.8 ➜ command conda        

CommandType     Name                                Version    Source
-----------     ----                                -------    ------
Alias           conda -> Invoke-Conda                0.0        Conda

I downgraded my pwsh version to 7.4.5 and it works well now:

base 3.12.8 ➜ pwsh --version
PowerShell 7.4.5
base 3.12.8  ➜ conda activate mvd-3d
mvd-3d 3.10.11 ➜ 

So I suppose there should be changes in pwsh 7.5.0 that makes Invoke-Conda incompatible with the latest pwsh version. How could I patch the file %USERPROFILE%\miniconda3\shell\condabin\Conda.psm1? (Shown as below)

I'm not very familiar with PowerShell, so I'm not sure if this is a bug that should be reported on GitHub Issues instead of Stack Overflow.

param([parameter(Position=0,Mandatory=$false)] [Hashtable] $CondaModuleArgs=@{})

# Defaults from before we had arguments.
if (-not $CondaModuleArgs.ContainsKey('ChangePs1')) {
    $CondaModuleArgs.ChangePs1 = $True
}

## ENVIRONMENT MANAGEMENT ######################################################

<#
    .SYNOPSIS
        Obtains a list of valid conda environments.

    .EXAMPLE
        Get-CondaEnvironment

    .EXAMPLE
        genv
#>
function Get-CondaEnvironment {
    [CmdletBinding()]
    param();

    begin {}

    process {
        # NB: the JSON output of conda env list does not include the names
        #     of each env, so we need to parse the fragile output instead.
        & $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA env list | `
            Where-Object { -not $_.StartsWith("#") } | `
            Where-Object { -not $_.Trim().Length -eq 0 } | `
            ForEach-Object {
                $envLine = $_ -split "\s+";
                $Active = $envLine[1] -eq "*";
                [PSCustomObject] @{
                    Name = $envLine[0];
                    Active = $Active;
                    Path = if ($Active) {$envLine[2]} else {$envLine[1]};
                } | Write-Output;
            }
    }

    end {}
}

<#
    .SYNOPSIS
        Activates a conda environment, placing its commands and packages at
        the head of $Env:PATH.

    .EXAMPLE
        Enter-CondaEnvironment base

    .EXAMPLE
        etenv base

    .NOTES
        This command does not currently support activating environments stored
        in a non-standard location.
#>
function Enter-CondaEnvironment {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$false)][switch]$Stack,
        [Parameter(Position=0)][string]$Name
    );

    begin {
        If ($Stack) {
            $activateCommand = (& $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA shell.powershell activate --stack $Name | Out-String);
        } Else {
            $activateCommand = (& $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA shell.powershell activate $Name | Out-String);
        }

        Write-Verbose "[conda shell.powershell activate $Name]`n$activateCommand";
        Invoke-Expression -Command $activateCommand;
    }

    process {}

    end {}

}

<#
    .SYNOPSIS
        Deactivates the current conda environment, if any.

    .EXAMPLE
        Exit-CondaEnvironment

    .EXAMPLE
        exenv
#>
function Exit-CondaEnvironment {
    [CmdletBinding()]
    param();

    begin {
        $deactivateCommand = (& $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA shell.powershell deactivate | Out-String);

        # If deactivate returns an empty string, we have nothing more to do,
        # so return early.
        if ($deactivateCommand.Trim().Length -eq 0) {
            return;
        }
        Write-Verbose "[conda shell.powershell deactivate]`n$deactivateCommand";
        Invoke-Expression -Command $deactivateCommand;
    }
    process {}
    end {}
}

## CONDA WRAPPER ###############################################################

<#
    .SYNOPSIS
        conda is a tool for managing and deploying applications, environments
        and packages.

    .PARAMETER Command
        Subcommand to invoke.

    .EXAMPLE
        conda install toolz
#>
function Invoke-Conda() {
    # Don't use any explicit args here, we'll use $args and tab completion
    # so that we can capture everything, INCLUDING short options (e.g. -n).
    if ($Args.Count -eq 0) {
        # No args, just call the underlying conda executable.
        & $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA;
    }
    else {
        $Command = $Args[0];
        if ($Args.Count -ge 2) {
            $OtherArgs = $Args[1..($Args.Count - 1)];
        } else {
            $OtherArgs = @();
        }
        switch ($Command) {
            "activate" {
                Enter-CondaEnvironment @OtherArgs;
            }
            "deactivate" {
                Exit-CondaEnvironment;
            }

            default {
                # There may be a command we don't know want to handle
                # differently in the shell wrapper, pass it through
                # verbatim.
                & $Env:CONDA_EXE $Env:_CE_M $Env:_CE_CONDA $Command @OtherArgs;
            }
        }
    }
}

## TAB COMPLETION ##############################################################
# We borrow the approach used by posh-git, in which we override any existing
# functions named TabExpansion, look for commands we can complete on, and then
# default to the previously defined TabExpansion function for everything else.

if (Test-Path Function:\TabExpansion) {
    # Since this technique is common, we encounter an infinite loop if it's
    # used more than once unless we give our backup a unique name.
    Rename-Item Function:\TabExpansion CondaTabExpansionBackup
}

function Expand-CondaEnv() {
    param(
        [string]
        $Filter
    );

    $ValidEnvs = Get-CondaEnvironment;
    $ValidEnvs `
        | Where-Object { $_.Name -like "$filter*" } `
        | ForEach-Object { $_.Name } `
        | Write-Output;
    $ValidEnvs `
        | Where-Object { $_.Path -like "$filter*" } `
        | ForEach-Object { $_.Path } `
        | Write-Output;

}

function Expand-CondaSubcommands() {
    param(
        [string]
        $Filter
    );

    # Filter and output applicable subcommands
    Invoke-Conda commands | Where-Object { $_ -like "$Filter*" } | Write-Output;

}

function TabExpansion($line, $lastWord) {
    $lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()

    switch -regex ($lastBlock) {
        # Pull out conda commands we recognize first before falling through
        # to the general patterns for conda itself.
        "^conda activate (.*)" { Expand-CondaEnv $lastWord; break; }
        "^etenv (.*)" { Expand-CondaEnv $lastWord; break; }

        # If we got down to here, check arguments to conda itself.
        "^conda (.*)" { Expand-CondaSubcommands $lastWord; break; }

        # Finally, fall back on existing tab expansion.
        default {
            if (Test-Path Function:\CondaTabExpansionBackup) {
                CondaTabExpansionBackup $line $lastWord
            }
        }
    }
}

## PROMPT MANAGEMENT ###########################################################

<#
    .SYNOPSIS
        Modifies the current prompt to show the currently activated conda
        environment, if any.
    .EXAMPLE
        Add-CondaEnvironmentToPrompt

        Causes the current session's prompt to display the currently activated
        conda environment.
#>
if ($CondaModuleArgs.ChangePs1) {
    # We use the same procedure to nest prompts as we did for nested tab completion.
    if (Test-Path Function:\prompt) {
        Rename-Item Function:\prompt CondaPromptBackup
    } else {
        function CondaPromptBackup() {
            # Restore a basic prompt if the definition is missing.
            "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) ";
        }
    }

    function global:prompt() {
        if ($Env:CONDA_PROMPT_MODIFIER) {
            $Env:CONDA_PROMPT_MODIFIER | Write-Host -NoNewline
        }
        CondaPromptBackup;
    }
}

## ALIASES #####################################################################

New-Alias conda Invoke-Conda -Force
New-Alias genv Get-CondaEnvironment -Force
New-Alias etenv Enter-CondaEnvironment -Force
New-Alias exenv Exit-CondaEnvironment -Force

## EXPORTS ###################################################################

Export-ModuleMember `
    -Alias * `
    -Function `
        Invoke-Conda, `
        Get-CondaEnvironment, `
        Enter-CondaEnvironment, Exit-CondaEnvironment, `
        TabExpansion, prompt
like image 786
SaturnTsen Avatar asked Dec 01 '25 09:12

SaturnTsen


1 Answers

Fix: Conda Not Working in PowerShell 7.5+ Due to _CE_M and _CE_CONDA Issue

Issue Summary

After upgrading to PowerShell 7.5.0, Conda commands fail with the following error:

usage: conda-script.py [-h] [-v] [--no-plugins] [-V] COMMAND ...
conda-script.py: error: argument COMMAND: invalid choice: ''
  • Running Get-Command conda shows Alias conda -> Invoke-Conda, meaning Conda is still aliased correctly.
  • Manually setting _CE_M and _CE_CONDA to $null fixes the issue:
    $Env:_CE_M = $Env:_CE_CONDA = $null
    conda activate my_env  # Works after setting these variables
    

Root Cause

  • PowerShell 7.5+ (built on .NET 9) changed how environment variables behave.
  • Setting $Env:_CE_M = '' no longer removes the variable, which breaks Conda’s command parsing.
  • This issue does not occur in PowerShell 5.1 or PowerShell 7.4 and earlier.

Final Fix: Apply Automatic Clearing of _CE_M and _CE_CONDA Only in PowerShell 7.5+

Instead of manually running $Env:_CE_M = $null; $Env:_CE_CONDA = $null before every Conda command, we can apply a fix in $PROFILE to automate this only in PowerShell 7.5+.


Solution: Modify PowerShell 7.5+ Profile

1. Open the PowerShell 7.5+ Profile

notepad $PROFILE

Note:

  • PowerShell 5.1 profile is in: C:\Users\jim\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
  • PowerShell 7+ profile is in: C:\Users\jim\Documents\PowerShell\Microsoft.PowerShell_profile.ps1

Ensure you are modifying the PowerShell 7+ profile.


2. Add This Fix at the End of the File

Write-Host "Running 4th: CurrentUserCurrentHost" -ForegroundColor Magenta
Write-Host "Path: $($PROFILE.CurrentUserCurrentHost)" -ForegroundColor Magenta

# Conda Initialization
(& "D:\anaconda\Scripts\conda.exe" "shell.powershell" "hook") | Out-String | ?{$_} | Invoke-Expression

# Fix for Conda issue in PowerShell 7.5+ (caused by .NET 9 changes)
if ($PSVersionTable.PSVersion -ge [version]"7.5.0") {
    $ExecutionContext.InvokeCommand.PreCommandLookupAction = {
        param ($CommandName, $CommandOrigin)
        if ($CommandName -eq "conda") {
            $Env:_CE_M = $null
            $Env:_CE_CONDA = $null
        }
    }
}

3. Reload Your Profile

. $PROFILE

4. Verify the Fix

Run:

conda --version
conda activate my_env

If everything works, Conda should activate correctly in PowerShell 7.5+.


Why This Fix Works

  • Preserves PowerShell 5.1 behavior (no changes made there).
  • Only affects PowerShell 7.5+ (using $PSVersionTable.PSVersion).
  • Automatically fixes Conda commands without modifying aliases or breaking out-of-box behavior.
  • More efficient than overriding Invoke-Conda or removing aliases.

This clean fix ensures that Conda works correctly in both PowerShell 7.5+ and PowerShell 5.1.

like image 83
Jim McGuffin Avatar answered Dec 04 '25 00:12

Jim McGuffin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!