dagger/dagger · critical · ExceptionGroup
{download_error} failed to use CLI from PATH {cli_bin!r}: {e
Error message
{download_error}
failed to use CLI from PATH {cli_bin!r}: {e} What it means
An ExceptionGroup raised when both the primary (downloaded CLI) and the fallback (CLI from PATH) provisioning attempts fail. The download failed earlier (download_error), and then starting/connecting to the PATH dagger binary also raised an exception. Both errors are surfaced together so the root causes aren't hidden.
Source
Thrown at sdk/python/src/dagger/provisioning/_engine.py:111
download_error = None
try:
cli_bin = await self.get_cli()
except CLIReleaseUnavailableError as e:
download_error = e
cli_bin = fallback_to_local_cli(e, self.cfg.log_output)
await self.progress.update("Creating new Engine session")
try:
connect_params = await self.stack.enter_async_context(
start_cli_session(self.cfg, cli_bin)
)
except Exception as e:
if download_error is not None:
msg = (
f"{download_error}\nfailed to use CLI from PATH "
f"{cli_bin!r}: {e}"
)
raise ExceptionGroup(msg, [download_error, e]) from e
raise
self.connect_params = connect_params
self.connect_config = ConnectConfig(
timeout=self.cfg.timeout,
retry=self.cfg.retry,
)
return self
async def get_cli(self) -> str:
"""Get path to CLI."""
if cli_bin := os.getenv("_EXPERIMENTAL_DAGGER_CLI_BIN"):
return cli_bin
# Get from cache or download.
return await Downloader(progress=self.progress)
View on GitHub (pinned to 82ba2681db)
Solutions
- Fix the first error in the group (the download failure) — network, proxy, or pinned version availability.
- Verify the PATH dagger binary runs standalone (`dagger version`); reinstall or upgrade it if it errors.
- Ensure the PATH CLI version is compatible with the SDK version you are using.
- Remove conflicting DAGGER_SESSION_* env vars so provisioning starts a fresh engine.
- In CI, pin a known-good dagger CLI install step so the fallback is healthy.
Defensive patterns
Strategy: fallback
Validate before calling
import shutil, subprocess
def path_cli_usable() -> bool:
b = shutil.which("dagger")
if not b:
return False
try:
return subprocess.run([b, "version"], capture_output=True, timeout=10).returncode == 0
except Exception:
return False
# if not path_cli_usable(): fix the local CLI before provisioning Try / catch
try:
async with dagger.Connection() as client:
...
except ExceptionGroup as eg:
for sub in eg.exceptions:
logger.error("provisioning failed: %r", sub)
raise # fix download network AND local dagger install Prevention
- Keep the PATH dagger CLI healthy and version-compatible with the SDK (`dagger version` must work).
- Fix network/proxy issues so the primary download path succeeds.
- Pin CLI and SDK versions together and upgrade them in lockstep.
- Bake a working dagger CLI into CI images.
When it happens
Trigger: In provision(), after a failed download (download_error set), the code tries to start/connect using the PATH dagger binary cli_bin; any exception in that path is re-raised as ExceptionGroup([download_error, e]) with this combined message.
Common situations: Download blocked by network issues AND the PATH dagger is an incompatible/broken version that fails to start (e.g. engine version incompatibility, missing exec permission); both the pinned download and local binary unusable in restricted CI environments.
Related errors
- {download_error} dagger CLI not found in PATH: {path_error}
- %w: %w
- Failed to download checksums from {self.checksum_url}: {e}
- Failed to download archive from {self.archive_url}: {e}
- Downloaded CLI binary checksum ({actual_hash}) does not matc
AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05).
Data as JSON: /api/errors/711fb6b33be14e97.
Report an issue: GitHub.