Repository navigation
[App Service] az webapp ssh silently exits on macOS with Python 3.14 and Invoke 2.2.0 #34005
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: pyinvoke/invoke#1038
Python 3.14 tracking: #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:
"$(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:
- Package a Python 3.14-compatible Invoke version.
- Do not suppress the session exception and report success when SSH failed.
Activity
yonzhan commentedon Aug 27, 2026
Thank you for opening this issue, we will look into it.
x-engineering-agent commentedon Aug 27, 2026
Bug Analysis
az webapp ssh(implemented insrc/azure-cli/azure/cli/command_modules/appservice/custom.py, function_start_ssh_session) establishes an App Service tunnel and opens a Paramiko SSH channel, then hands off to an interactive terminal via the bundledinvoke/fabriclibraries.On macOS with Python 3.14 (e.g. Homebrew's azure-cli 2.89.1 build), the bundled
invoke==2.2.0callsfcntl.ioctl(sys.stdout, termios.TIOCGWINSZ, struct.pack('HH', 0, 0))— a 4-byte buffer — ininvoke/terminals.py. Python 3.14 added stricterioctlbuffer-size validation and raisesSystemError: buffer overflowfor the 8-byteTIOCGWINSZresponse landing in that 4-byte buffer.invokefixed this upstream by switching to the correct'HHHH'(8-byte) format in 2.2.1 (pyinvoke/invoke#1038).The real Azure CLI bug is that
_start_ssh_sessioncatches this (and any other) exception from the interactive session, logs it only at INFO/DEBUG level, closes the connection, and lets the command return exit code 0 as if the SSH session succeeded. Users get no visible error and a misleading success exit status.Fix: in
_start_ssh_session(or wherever the interactive session's exception is caught), do not swallow the exception silently — surface it to the user (e.g. raise aCLIError/AzureResponseErrorwith the underlying message, or at minimum log it at ERROR level) and ensure the process exits non-zero when the interactive terminal fails to start, instead of returning success. Do not attempt to vendor a newerinvokeversion as part of this fix — that is a packaging/dependency concern outside this PR's scope; focus only on not masking the failure.Reproduction: macOS, Python 3.14.7, Azure CLI 2.89.1 (Homebrew), bundled Invoke 2.2.0. Running
az webapp ssh --resource-group <rg> --name <app>with--debugshowsazure.cli.command_modules.appservice.custom: buffer overflowfollowed byaz_command_data_logger: exit code: 0.Use this EXACT PR title:
[AppService] Fix #34005:az webapp ssh: Report SSH session failures instead of exiting 0Mandatory Codegen execution protocol
Before editing implementation files, determine whether the affected
appservicecommand is AAZ-generated. Files underaaz/<profile>/are generated output and must never be patched directly, including by an AI agent. Check outAzure/aazbesideAzure/azure-rest-api-specs,Azure/aaz-dev-tools, and the downstream repository. API-schema defects start in the specification; command naming, grouping, arguments, API-version selection, help, and examples belong in the durableAzure/aazcommand model; non-modelable client behavior belongs in a handwritten subclass or wrapper incustom.py, registered fromcommands.py. Agent Assist creates and promotes the corresponding durableAzure/aazsource pull request before it promotes downstream generated output.Follow the Azure CLI repository's Codegen workflow and the aaz-dev setup documentation. Set up the checked-out repositories with
azdev setup. Usegenerateonly when importing or redesigning command models from Swagger/TypeSpec. For an existing module whose durableAzure/aazmodel has been updated, render that model withregenerate:You MUST actually run the generator; do not merely describe it or imitate its output. If the AAZ/specification checkout, local source change, credentials, or generator is unavailable, stop and report the blocker instead of editing generated files. Inspect
_aaz_infoprovenance and the complete regenerated diff, then run focusedazdev style,azdev linter, andazdev testvalidation. For an extension, also update its version andHISTORY.rst, preserveazext_metadata.jsoncompatibility, and let release automation updatesrc/index.json.PR title & description format (required)
This repo enforces a PR format (guide). Please author the PR exactly as follows or CI's Check the Format of Pull Request Title and Content will fail.
Use this EXACT PR title (copy verbatim, do not reword):
Keep the backticks around the command and the
Fix #34005:prefix. You may only adjust the wording after the command (the final summary) if the fix changes; the[AppService]prefix, issue link, and backticked command must stay.Description — follow the PR template and fill in:
Fixes #34005.az ...command this affects.[AppService] `az <command>`: <note>.x-engineering-agent commentedon Aug 27, 2026
Started a Copilot task in
a0x1ab/azure-cliusingclaude-sonnet-4.6: https://github.com/a0x1ab/azure-cli/tasks/1e6a0669-428c-4e10-bbe7-8e33a0db4090[AppService] Fix Azure#34005: `az webapp ssh`: Report SSH session fai…
microsoft-github-policy-service commentedon Oct 14, 2026
🔔 Routing this issue to @Azure/act-observability-squad.
microsoft-github-policy-service commentedon Oct 14, 2026
Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc AzureAppServiceCLI (@AzureAppServiceCLI), antcp, @yutanglin16, @Azure/act-observability-squad.