Skip to content

Keep the gateway connection when a tunnel fails to open - #60

Merged
czpython merged 1 commit into
mainfrom
gateway-tunnel-failure
Sep 28, 2026
Merged

czpython merged 1 commit into
mainfrom
gateway-tunnel-failure

Conversation

@czpython

@czpython czpython commented Sep 28, 2026 •

Copy link
Copy Markdown
Owner

asyncssh reads the local login name for every client connection, also when the call gives username. A deployment can run the image as a uid with no passwd entry, for example user: 1000:1000 to reach the sbx socket. Then the lookup raises ValueError. The error escaped connection_requested, thus asyncssh closed the whole caller connection.

asyncssh 2.24.0 has no option that sets the local name, so open_gateway_tunnel cannot pass one. Thus the change has two parts:

  • The image sets LOGNAME=appuser. getpass reads LOGNAME before it looks up the uid.
  • DockerSbxProvider.open_gateway_tunnel turns a ValueError from asyncssh into ProviderTransportError. The gateway already turns a ProviderError into ChannelOpenError(OPEN_CONNECT_FAILED), so only the channel fails.

The gateway still catches only ProviderError. Providers translate their own failures at the boundary, and a defect in the gateway must not look like a connection failure.

Validation:

  • uv run pytest: 739 passed on SQLite. Ruff, format checks, and Pyright passed.
  • A new provider test makes getpass.getuser raise KeyError, as it does on Python 3.11 for a uid with no passwd entry. open_gateway_tunnel raises ProviderTransportError. Without the change, the ValueError escapes.
  • The gateway test for a failed tunnel now runs a command on the same connection after the refusal.
  • The built image, run as 1000:1000, resolves the login name, and asyncssh builds its client options. With LOGNAME cleared, it fails with getpwuid(): uid not found: 1000.

A gateway that runs outside the image as a uid with no name still needs LOGNAME or USER in its environment.

Fixes #59.

asyncssh reads the local login name for every client connection. A
deployment can run the image as a uid with no passwd entry, and then
the lookup raises ValueError. The error escaped connection_requested,
thus asyncssh closed the whole caller connection.

The image now sets LOGNAME, which getpass reads first. The docker-sbx
provider turns a ValueError from asyncssh into ProviderTransportError,
so the gateway fails only the channel.

Fixes #59.
@czpython
czpython force-pushed the gateway-tunnel-failure branch from fbe639c to e12f902 Compare September 28, 2026 09:03
@czpython
czpython merged commit f4c2640 into main Sep 28, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Gateway tunnel fails when the container user has no name

1 participant