microsoft/aspire · error · InvalidOperationException

The 'rad' CLI was not found. Please install it from

Error message

The 'rad' CLI was not found. Please install it from {RadInstallUrl} and ensure it is available on your PATH.

What it means

RadiusDeploymentPipelineStep.ExecuteAsync detects the rad CLI before generating and running Bicep deployments for the environment. If DetectRadCliAsync reports rad is absent, it logs the same message and throws CreateRadCliNotFoundException, halting the deployment. The rad CLI is required to translate and apply the generated Bicep against the Radius control plane.

Solutions

  1. Install the rad CLI (https://radapp.io) and confirm with 'rad --version' in the same shell/agent that runs the deploy
  2. Add rad's install location to PATH for the deploy process (export PATH=... or CI environment PATH update)
  3. Add an explicit rad-install step to your pipeline before aspire publish/deploy
  4. Use a base image or dev container that preinstalls rad

Example fix

// before
- run: aspire publish -o artifacts  // fails: rad not on PATH

// after
- run: |
    curl -fsSL https://get.radapp.dev/install.sh | bash
    echo "$HOME/.rad/bin" >> "$GITHUB_PATH"
- run: aspire publish -o artifacts
Defensive patterns

Strategy: validation

Validate before calling

# Guard the deploy pipeline
if ! command -v rad >/dev/null 2>&1; then
  echo "rad CLI missing; install from https://radapp.io"; exit 1
fi
rad version

Try / catch

try
{
    await pipelineStep.ExecuteAsync(context, ct);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("'rad' CLI was not found"))
{
    // Setup issue: install rad on PATH and re-run; deployment made no changes.
    throw;
}

Prevention

When it happens

Trigger: Executing the Radius deployment pipeline step (aspire publish/deploy targeting a Radius environment) where the 'rad' executable is not found on the PATH of the deploying process.

Common situations: New CI runner without rad; rad installed locally but PATH not propagated into the publish process; deploying from an IDE terminal with a different PATH than the shell; containerized builds lacking the Radius CLI; forgetting installation after switching machines.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/5622aa953aeed2d4. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Radius/Publishing/RadiusDeploymentPipelineStep.cs:518

            Action = ExecuteAsync
        };
        step.DependsOn($"publish-radius-{_environment.Name}");
        step.RequiredBy(WellKnownPipelineSteps.Deploy);
        step.DependsOn(WellKnownPipelineSteps.DeployPrereq);
        return step;
    }

    internal async Task ExecuteAsync(PipelineStepContext context)
    {
        var cancellationToken = context.CancellationToken;
        var logger = context.Logger;

        // Detect rad CLI availability
        var radAvailable = await DetectRadCliAsync(cancellationToken).ConfigureAwait(false);
        if (!radAvailable)
        {
            logger.LogError("The 'rad' CLI was not found on PATH. Install it from {InstallUrl}", RadInstallUrl);
            throw CreateRadCliNotFoundException();
        }

        logger.LogInformation("rad CLI detected on PATH for environment '{EnvironmentName}'", _environment.Name);

        // Resolve the output directory where Bicep was generated
        var outputDir = PublishingContextUtils.GetEnvironmentOutputPath(context, _environment);
        var bicepPath = Path.Combine(outputDir, "app.bicep");

        if (!File.Exists(bicepPath))
        {
            logger.LogError("Bicep file not found at {BicepPath}. Ensure the publish step completed successfully.", bicepPath);
            throw new InvalidOperationException(
                $"Bicep file not found at '{bicepPath}'. Ensure the publish step completed successfully before deploying.");
        }

        logger.LogInformation("Starting rad deploy with Bicep file '{BicepPath}'", bicepPath);

        // Declared outside the try so the finally can always clean up the temp secrets file, even

View on GitHub (pinned to 25830f84bd)