Azure / Azure/azure-cli

az.cmd truncates multi-line arguments on windows

Open
#32,644 6 comments 1 reaction 2 assignees Assigned to @a0x1ab View on GitHub
act-platform-engineering-squad Auto-Assign bug customer-reported DevOps Language Service Attention
Dominant language
Python
Stars
4.6k
Forks
3.5k
Avg merge
3d 2h
Merged PRs (30d)
60

Description

### Describe the bug

On Windows, command-line arguments containing embedded newlines are truncated at the first newline when invoking `az` commands. This affects any argument that a user might want to pass as a multiline string (e.g., `--description`, `--message`, etc.).

## Root Cause

The Azure CLI on Windows is invoked through `az.cmd`, a batch script wrapper located at `C:\Program Files\Microsoft SDKs\Azure\CLI2\wbin\az.cmd`:

```batch
@IF EXIST "%~dp0\..\python.exe" (
SET AZ_INSTALLER=MSI
"%~dp0\..\python.exe" -IBm azure.cli %*
) ELSE (
echo Failed to load python executable.
exit /b 1
)
```

The `%*` batch variable expansion in `cmd.exe` does not correctly handle arguments containing newline characters. When an argument contains a newline, everything after the first newline is lost.

## Reproduction Steps

### 1. Create a test Python script `test_args.py`:

```python
import argparse
import sys

print(f"sys.argv: {sys.argv}")

parser = argparse.ArgumentParser()
parser.add_argument('--description', nargs='*')
args = parser.parse_args()

print(f"description: {repr(args.description)}")
```

### 2. Create a batch wrapper `test_wrapper.cmd`:

```batch
@"C:\Program Files\Microsoft SDKs\Azure\CLI2\python.exe" C:\path\to\test_args.py %*
```

### 3. Run from PowerShell with a multiline argument:

**Through batch wrapper (FAILS):**

```powershell
C:\path\to\test_wrapper.cmd --description "Line 1

Line 2"
```

Output:
```
sys.argv: ['C:\\path\\to\\test_args.py', '--description', 'Line 1']
description: ['Line 1']
```

**Direct Python call (WORKS):**

```powershell
& "C:\Program Files\Microsoft SDKs\Azure\CLI2\python.exe" C:\path\to\test_args.py --description "Line 1

Line 2"
```

Output:
```
sys.argv: ['C:\\path\\to\\test_args.py', '--description', 'Line 1\n\nLine 2']
description: ['Line 1\n\nLine 2']
```

### 4. Real-world example with Azure CLI:

**Through az.cmd (FAILS):**

```powershell
az repos pr create --description "First paragraph

Second paragraph" ...
```

Only "First paragraph" is received.

**Direct Python invocation (WORKS):**

```powershell
& "C:\Program Files\Microsoft SDKs\Azure\CLI2\python.exe" -m azure.cli repos pr create --description "First paragraph

Second paragraph" ...
```

Full multiline description is received.

## Expected Behavior

Multiline arguments should be passed intact to the Azure CLI Python code, preserving all newlines.

## Actual Behavior

Arguments are truncated at the first newline character when using the `az` command on Windows.

## Environment

- OS: Windows 10/11
- Shell: PowerShell (though the issue is in cmd.exe batch processing)
- Azure CLI: Any version using the .cmd wrapper

## Potential Solutions

### 1. Replace az.cmd with az.exe (Recommended)

Create a native Windows executable wrapper (`az.exe`) instead of using a batch script. This is how many other CLI tools (git, node, etc.) handle Windows invocation and avoids cmd.exe argument parsing issues entirely.

### 2. Use PowerShell wrapper for PowerShell users

Provide an `az.ps1` wrapper that PowerShell would invoke directly (PowerShell prefers .ps1 over .cmd in PATH), bypassing cmd.exe:

```powershell
& "$PSScriptRoot\..\python.exe" -IBm azure.cli @args
```

### 3. Document the limitation

At minimum, document this Windows-specific limitation and provide workarounds:

- Use escape sequences: `--description "Line 1`n`nLine 2"` (PowerShell)
- Use a variable: `$desc = "Line 1↵Line 2"; az ... --description $desc`
- Call Python directly: `& "C:\Program Files\Microsoft SDKs\Azure\CLI2\python.exe" -m azure.cli ...`

## Impact

This affects any Azure CLI command where users might want to pass multiline content, including:

- `az repos pr create --description`
- `az repos pr update --description`
- `az boards work-item create --description`
- Any other command accepting freeform text arguments

## Workarounds

Until this is fixed, users can work around the issue by:

1. **Using PowerShell escape sequences:**
```powershell
az repos pr create --description "Line 1`n`nLine 2" ...
```

2. **Storing the description in a variable first:**
```powershell
$description = "Line 1

Line 2"
az repos pr create --description $description ...
```

3. **Using a here-string:**
```powershell
$description = @"
Line 1

Line 2
"@
az repos pr create --description $description ...
```

4. **Calling Python directly (bypassing az.cmd):**
```powershell
& "C:\Program Files\Microsoft SDKs\Azure\CLI2\python.exe" -m azure.cli repos pr create --description "Line 1

Line 2" ...
```

## Related

This is a known limitation of cmd.exe batch argument handling and affects other tools that use .cmd wrappers on Windows.

### Related command

```powershell
az repos pr create --description "First paragraph

Second paragraph" ...
```

### Errors

no visible errors

### Issue script & Debug output

```powershell
az repos pr create --description "First paragraph

Second paragraph" ...
```

### Expected behavior

Expect untruncated output

### Environment Summary

azure-cli 2.82.0

core 2.82.0
telemetry 1.1.0

Extensions:
azure-devops 1.0.3

Dependencies:
msal 1.34.0b1
azure-mgmt-resource 23.3.0

Python location 'C:\Program Files\Microsoft SDKs\Azure\CLI2\python.exe'
Config directory 'C:\Users\timmydo\.azure'
Extensions directory 'C:\Users\timmydo\.azure\cliextensions'

Python (Windows) 3.13.9 (tags/v3.13.9:8183fa5, Oct 14 2025, 14:09:13) [MSC v.1944 64 bit (AMD64)]

Legal docs and information: aka.ms/AzureCliLegal

Your CLI is up-to-date.

### Additional context

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.