[Bug] TLS error message & documentation for API key auth
If you're using Temporal Cloud with API key authentication for a namespace:
$ tcld namespace auth-method get -namespace quickstart-jack.xxxxx
api_key
And connecting with Python:
TASK_QUEUE = os.environ.get("TASK_QUEUE", "tasks")
TEMPORAL_ADDRESS = os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")
TEMPORAL_NAMESPACE = os.environ.get("TEMPORAL_NAMESPACE", "default")
TEMPORAL_API_KEY = os.environ.get("TEMPORAL_API_KEY", "")
async def main() -> None:
client = await Client.connect(TEMPORAL_ADDRESS, namespace=TEMPORAL_NAMESPACE, api_key=TEMPORAL_API_KEY)
executor = ThreadPoolExecutor()
worker = Worker(
client,
task_queue=TASK_QUEUE,
workflows=load_workflows(),
activities=load_activities(),
activity_executor=executor,
)
await worker.run()
This will raise this error:
$ poetry run python worker.py
Traceback (most recent call last):
File "/Users/pearkes/code/jack/temporal/worker.py", line 75, in <module>
asyncio.run(main())
~~~~~~~~~~~^^^^^^^^
File "/Users/pearkes/.local/share/uv/python/cpython-3.13.2-macos-aarch64-none/lib/python3.13/asyncio/runners.py", line 195, in run
return runner.run(main)
~~~~~~~~~~^^^^^^
File "/Users/pearkes/.local/share/uv/python/cpython-3.13.2-macos-aarch64-none/lib/python3.13/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
File "/Users/pearkes/.local/share/uv/python/cpython-3.13.2-macos-aarch64-none/lib/python3.13/asyncio/base_events.py", line 725, in run_until_complete
return future.result()
~~~~~~~~~~~~~^^
File "/Users/pearkes/code/jack/temporal/worker.py", line 62, in main
client = await Client.connect(TEMPORAL_ADDRESS, namespace=TEMPORAL_NAMESPACE, api_key=TEMPORAL_API_KEY)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/pearkes/code/jack/temporal/.venv/lib/python3.13/site-packages/temporalio/client.py", line 177, in connect
await temporalio.service.ServiceClient.connect(connect_config), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/pearkes/code/jack/temporal/.venv/lib/python3.13/site-packages/temporalio/service.py", line 209, in connect
return await _BridgeServiceClient.connect(config) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/pearkes/code/jack/temporal/.venv/lib/python3.13/site-packages/temporalio/service.py", line 1212, in connect await client._connected_client()
File "/Users/pearkes/code/jack/temporal/.venv/lib/python3.13/site-packages/temporalio/service.py", line 1225, in _connected_client self._bridge_client = await temporalio.bridge.client.Client.connect(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...<2 lines>... ) ^
File "/Users/pearkes/code/jack/temporal/.venv/lib/python3.13/site-packages/temporalio/bridge/client.py", line 97, in connect await temporalio.bridge.temporal_sdk_bridge.connect_client( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
runtime._ref, config ^^^^^^^^^^^^^^^^^^^^
), ^
RuntimeError: Failed client connect: `get_system_info` call error after connection: Status { code: Unknown, message: "transport error", source: Some(tonic::transport::Error(Transport, hyper::Error(Io, Kind(ConnectionReset)))) }
-
Status { code: Unknown, message: "transport error" ...is quite inscrutable and could be considerably improved. - You need to set TLS to
True– this wasn't clear in the getting started docs, nor were API keys as an auth method mentioned. I found a reference to it in the Python client docs and figured that may be it.
This works:
TASK_QUEUE = os.environ.get("TASK_QUEUE", "tasks")
TEMPORAL_ADDRESS = os.environ.get("TEMPORAL_ADDRESS", "localhost:7233")
TEMPORAL_NAMESPACE = os.environ.get("TEMPORAL_NAMESPACE", "default")
TEMPORAL_API_KEY = os.environ.get("TEMPORAL_API_KEY", "")
TEMPORAL_TLS = bool(os.environ.get("TEMPORAL_TLS", False))
async def main() -> None:
client = await Client.connect(TEMPORAL_ADDRESS, namespace=TEMPORAL_NAMESPACE, api_key=TEMPORAL_API_KEY, tls=TEMPORAL_TLS)
# Use a thread pool executor for synchronous activities
executor = ThreadPoolExecutor()
worker = Worker(
client,
task_queue=TASK_QUEUE,
workflows=load_workflows(),
activities=load_activities(),
activity_executor=executor,
)
await worker.run()
Status { code: Unknown, message: "transport error" ... is quite inscrutable and could be considerably improved.
For security reasons, often attempting to connect to TLS endpoint without TLS doesn't give too many details. This is reported by our Rust extension when the connection fails. We may be able to improve some of the phrasing if "transport error" is unclear, but it'll still be a basic "reset".
this wasn't clear in the getting started docs, nor were API keys as an auth method mentioned
The API key methods and the TLS settings are currently being improved by our docs team (in https://github.com/temporalio/documentation)
Cool, thanks. Maybe a client side description of the error that points to further documentation, or similar? Understood it's a pretty generic error.
Transferring to sdk-core where the error message originates...