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

  1. 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.
  2. Verify cluster connectivity and credentials: kubectl cluster-info / kubectl config current-context with the kubeconfig Aspire is using.
  3. 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.
  4. 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

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


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)