microsoft/aspire · error · InvalidOperationException
helm upgrade --install failed with exit code
Error message
helm upgrade --install failed with exit code {exitCode} What it means
The 'helm upgrade --install' process that deploys the release exited with a non-zero exit code, so the deployment step fails. When helm wrote anything to stderr, the message includes that output ('helm upgrade --install failed: <stderr>'); otherwise only the exit code is reported. This wraps any helm-side failure: bad chart, unreachable cluster, failed hooks, etc.
Solutions
- Read the stderr detail in the full message ('helm upgrade --install failed: ...') - it usually names the exact helm failure; run the same helm command manually to reproduce.
- Verify cluster connectivity and credentials: kubectl cluster-info / kubectl config current-context with the kubeconfig Aspire is using.
- If the message is only the exit code, re-run the deployment with verbose logging (helm stderr is logged at Debug level) to capture the underlying helm error.
- Fix the reported chart/resource problem (missing chart files, invalid values, quota exceeded, missing CRDs) and redeploy.
Defensive patterns
Strategy: retry
Validate before calling
// before deploying, verify cluster reachability with the kubeconfig the app host uses: // kubectl cluster-info --context <context> (non-zero exit means fix credentials/context first) // and confirm the chart directory exists at the published path.
Try / catch
try
{
await deploymentEngine.DeployAsync(context);
}
catch (InvalidOperationException ex) when (ex.Message.StartsWith("helm upgrade --install failed"))
{
// surface ex.Message verbatim - it embeds helm's stderr
logger.LogError(ex, "Helm deploy failed for environment {Env}", context.Environment.Name);
throw; // or retry transient failures (network, timeouts) with backoff
} Prevention
- Pre-validate kubeconfig and context (kubectl cluster-info) before running Aspire deploy in automation.
- Ensure the chart/values are generated (aspire publish) before deploy so helm finds the chart path.
- Enable debug logging to capture helm stdout/stderr for diagnosis.
- Install CRDs and quotas the chart needs before 'helm upgrade --install'.
When it happens
Trigger: HelmDeployAsync launches helm upgrade --install and the process returns a non-zero exit code - e.g. the kubeconfig/context is wrong, the cluster is unreachable, the chart is invalid, a template render fails, a resource conflict occurs, or a Helm hook fails.
Common situations: Expired or missing kubeconfig credentials, wrong kubectl context, chart files not present at the expected path after publish, CRDs not installed before the release, or resource quota/ admission webhook rejections in the cluster.
Related errors
- Destroy operation canceled by user.
- helm uninstall failed with exit code
- Cannot derive a Helm release name from resource name
- Cannot derive a Kubernetes namespace from resource name
- Chart description must be a string or a parameter resource…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/65ef0ed33e9c1a66.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Kubernetes/Deployment/HelmDeploymentEngine.cs:485
var exitCode = await helmRunner.RunAsync(
arguments.ToString(),
workingDirectory: outputPath,
onOutputData: output => context.Logger.LogDebug("helm (stdout): {Output}", output),
onErrorData: error =>
{
stderrBuilder.AppendLine(error);
context.Logger.LogDebug("helm (stderr): {Error}", error);
},
cancellationToken: context.CancellationToken).ConfigureAwait(false);
if (exitCode != 0)
{
var errorOutput = stderrBuilder.ToString().Trim();
var message = string.IsNullOrEmpty(errorOutput)
? $"helm upgrade --install failed with exit code {exitCode}"
: $"helm upgrade --install failed: {errorOutput}";
throw new InvalidOperationException(message);
}
else
{
// Persist deployment state so destroy can find the release
var deploymentStateManager = context.Services.GetRequiredService<IDeploymentStateManager>();
var stateSection = await deploymentStateManager.AcquireSectionAsync($"Helm:{environment.Name}", context.CancellationToken).ConfigureAwait(false);
stateSection.Data["ReleaseName"] = releaseName;
stateSection.Data["Namespace"] = @namespace;
await deploymentStateManager.SaveSectionAsync(stateSection, context.CancellationToken).ConfigureAwait(false);
await deployTask.CompleteAsync(
new MarkdownString($"Helm release **{releaseName}** deployed to namespace **{@namespace}**"),
CompletionState.Completed,
context.CancellationToken).ConfigureAwait(false);
}
}
catch (Exception ex) when (ex is not OperationCanceledException)
{View on GitHub (pinned to 25830f84bd)