microsoft/aspire · error · InvalidOperationException
Bicep file not found at
Error message
Bicep file not found at '{bicepPath}'. Ensure the publish step completed successfully before deploying. What it means
Before running `rad deploy`, RadiusDeploymentPipelineStep expects the publish phase to have produced app.bicep under the environment's output directory. If the file does not exist, deployment cannot proceed, so the step logs and throws this InvalidOperationException.
Solutions
- Run the publish step before deploy so app.bicep is generated.
- Check the earlier publish step's logs for the real failure and fix it.
- Verify the environment's output directory (artifacts path) matches where publish wrote the Bicep; do not delete artifacts between publish and deploy.
Example fix
// before (pipeline setup) await pipeline.RunAsync(deployStep, ...); // publish never ran // after await pipeline.RunAsync(publishStep, ...); await pipeline.RunAsync(deployStep, ...);
Defensive patterns
Strategy: validation
Validate before calling
// Ensure publish ran and produced the Bicep before deploying
var bicepPath = Path.Combine(outputDir, "app.bicep");
if (!File.Exists(bicepPath))
throw new InvalidOperationException($"Publish must run before deploy; missing {bicepPath}"); Try / catch
try { await deployStep.ExecuteAsync(context, ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Bicep file not found"))
{
logger.LogError(ex, "app.bicep missing — the publish step likely failed or was skipped; inspect publish logs.");
} Prevention
- Always run the publish step before the deploy step in the pipeline
- Check the publish step's exit/logs before starting deploy
- Do not clean the artifacts/output directory between publish and deploy
- Verify the environment's output path configuration matches where publish writes
When it happens
Trigger: Calling deploy (ExecuteAsync on RadiusDeploymentPipelineStep) when the publish step that generates app.bicep did not run, failed midway, or wrote to a different output directory (e.g. PublishingContextUtils.GetEnvironmentOutputPath points elsewhere).
Common situations: Running only the deploy step in a custom pipeline without running publish first; a prior publish step failed and the pipeline continued; cleaned or deleted artifacts/ output between steps; misconfigured environment output path.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- ("rad deploy failed with exit code " or "rad deploy failed…
- A ConfigureRadiusInfrastructure callback renamed container
- A ConfigureRadiusInfrastructure callback replaced container
- A ConfigureRadiusInfrastructure callback replaced port
- A ConfigureRadiusInfrastructure callback replaced the…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/83febbc177006171.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Radius/Publishing/RadiusDeploymentPipelineStep.cs:530
// 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
// if resolving/writing it (below) fails partway.
string? parametersFilePath = null;
var deployTask = await context.ReportingStep.CreateTaskAsync(
$"Deploying Radius environment '{_environment.Name}' via rad deploy...",
cancellationToken).ConfigureAwait(false);
try
{
// Resolve secret/parameter values at deploy time and write them to an owner-only
// temporary ARM JSON parameters file. This supplies the `@secure()` Bicep params
// emitted by publish without inlining secrets into the artifact or exposing them on theView on GitHub (pinned to 25830f84bd)