Azure / Azure/azure-cli

[App Service] az webapp ssh silently exits on macOS with Python 3.14 and Invoke 2.2.0

Open
#34,005 3 comments 0 reactions 2 assignees Claimed by @madsd View on GitHub
act-observability-squad app-service-general app-service-networking Auto-Assign bug customer-reported Service Attention Web Apps
Dominant language
Python
Stars
4.6k
Forks
3.5k
Avg merge
3d 2h
Merged PRs (30d)
60

Description

### Describe the bug

On macOS with Azure CLI 2.89.1 installed by Homebrew, `az webapp ssh` establishes the App Service tunnel and opens a Paramiko SSH channel, but immediately closes without displaying an error. The command exits with status 0.

With `--debug`, the interactive session reports `buffer overflow`. Azure CLI catches the exception in `_start_ssh_session`, logs it only at INFO/debug level, closes the connection, and returns success.

The bundled Invoke 2.2.0 uses a 4-byte `"HH"` buffer for `TIOCGWINSZ`. Python 3.14 detects the 8-byte write on macOS and raises `SystemError: buffer overflow`. Updating Invoke to 2.2.1 fixes the command.

Upstream: https://github.com/pyinvoke/invoke/issues/1038
Python 3.14 tracking: https://github.com/Azure/azure-cli/issues/32869

### Related command

az webapp ssh --resource-group --name

### Errors

No error appears normally; the command silently returns with exit status 0.

With `--debug`:

```
paramiko.transport: Secsh channel 0 opened.
paramiko.transport: [chan 0] EOF sent (0)
azure.cli.command_modules.appservice.custom: buffer overflow
Client disconnected
websocket close: Connection failure.
az_command_data_logger: exit code: 0
```

### Issue script & Debug output

``shell
az webapp ssh \
--resource-group \
--name \
--debug
```

The tunnel and SSH channel are established, followed by:

```
paramiko.transport: Secsh channel 0 opened.
paramiko.transport: [chan 0] EOF sent (0)
azure.cli.command_modules.appservice.custom: buffer overflow
Client disconnected
websocket close: Connection failure.
az_command_data_logger: exit code: 0
```

Invoke 2.2.0's `invoke/terminals.py` contains:

```python
fmt = "HH"
buf = struct.pack(fmt, 0, 0)
result = fcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, buf)
```

Invoke 2.2.1 uses the correct 8-byte `"HHHH"` structure. Installing 2.2.1 into Azure CLI's environment makes the same command work.

### Expected behavior

The command should maintain an interactive SSH session. If terminal creation fails, Azure CLI should display the exception and return a nonzero status instead of silently closing with status 0.

### Environment Summary

azure-cli 2.89.1
core 2.89.1
telemetry 1.1.0

Installation: Homebrew
Python location: /opt/homebrew/Cellar/azure-cli/2.89.1/libexec/bin/python
Python: 3.14.7
Bundled Invoke: 2.2.0
Fabric: 3.2.2
OS: macOS 26.6.2
Architecture: arm64

### Additional context

Homebrew's current Azure CLI 2.89.1 formula depends on Python 3.14 and packages Invoke 2.2.0.

Working dependency update:

```shell
"$(brew --prefix azure-cli)/libexec/bin/python" \
-m pip install --ignore-installed "invoke==2.2.1"
```

Another workaround is `az webapp create-remote-connection` plus the system SSH client.

Suggested fixes:
1. Package a Python 3.14-compatible Invoke version.
2. Do not suppress the session exception and report success when SSH failed.

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.