{"record":{"id":"65ef0ed33e9c1a66","repo":"microsoft/aspire","slug":"helm-upgrade-install-failed-with-exit-code-exitcode","errorCode":null,"errorMessage":"helm upgrade --install failed with exit code {exitCode}","messagePattern":"helm upgrade --install failed with exit code (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Kubernetes/Deployment/HelmDeploymentEngine.cs","lineNumber":485,"sourceCode":"                var exitCode = await helmRunner.RunAsync(\n                    arguments.ToString(),\n                    workingDirectory: outputPath,\n                    onOutputData: output => context.Logger.LogDebug(\"helm (stdout): {Output}\", output),\n                    onErrorData: error =>\n                    {\n                        stderrBuilder.AppendLine(error);\n                        context.Logger.LogDebug(\"helm (stderr): {Error}\", error);\n                    },\n                    cancellationToken: context.CancellationToken).ConfigureAwait(false);\n\n                if (exitCode != 0)\n                {\n                    var errorOutput = stderrBuilder.ToString().Trim();\n                    var message = string.IsNullOrEmpty(errorOutput)\n                        ? $\"helm upgrade --install failed with exit code {exitCode}\"\n                        : $\"helm upgrade --install failed: {errorOutput}\";\n\n                    throw new InvalidOperationException(message);\n                }\n                else\n                {\n                    // Persist deployment state so destroy can find the release\n                    var deploymentStateManager = context.Services.GetRequiredService<IDeploymentStateManager>();\n                    var stateSection = await deploymentStateManager.AcquireSectionAsync($\"Helm:{environment.Name}\", context.CancellationToken).ConfigureAwait(false);\n                    stateSection.Data[\"ReleaseName\"] = releaseName;\n                    stateSection.Data[\"Namespace\"] = @namespace;\n                    await deploymentStateManager.SaveSectionAsync(stateSection, context.CancellationToken).ConfigureAwait(false);\n\n                    await deployTask.CompleteAsync(\n                        new MarkdownString($\"Helm release **{releaseName}** deployed to namespace **{@namespace}**\"),\n                        CompletionState.Completed,\n                        context.CancellationToken).ConfigureAwait(false);\n                }\n            }\n            catch (Exception ex) when (ex is not OperationCanceledException)\n            {","sourceCodeStart":467,"sourceCodeEnd":503,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Kubernetes/Deployment/HelmDeploymentEngine.cs#L467-L503","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// before deploying, verify cluster reachability with the kubeconfig the app host uses:\n// kubectl cluster-info --context <context>   (non-zero exit means fix credentials/context first)\n// and confirm the chart directory exists at the published path.","typeGuard":null,"tryCatchPattern":"try\n{\n    await deploymentEngine.DeployAsync(context);\n}\ncatch (InvalidOperationException ex) when (ex.Message.StartsWith(\"helm upgrade --install failed\"))\n{\n    // surface ex.Message verbatim - it embeds helm's stderr\n    logger.LogError(ex, \"Helm deploy failed for environment {Env}\", context.Environment.Name);\n    throw; // or retry transient failures (network, timeouts) with backoff\n}","preventionTips":["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'."],"tags":["kubernetes","helm","deployment","process-exit-code"],"backgroundTag":"command-failed","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T09:17:21.228Z"}