{"record":{"id":"622d8321cb602da4","repo":"derailed/k9s","slug":"chart-is-in-an-invalid-state","errorCode":null,"errorMessage":"chart is in an invalid state","messagePattern":"chart is in an invalid state","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/render/helm/chart.go","lineNumber":86,"sourceCode":"\t\trender.ToAge(metav1.Time{Time: h.Release.Info.LastDeployed.Time}),\n\t}\n\n\treturn nil\n}\n\n// Healthy checks component health.\nfunc (c Chart) Healthy(_ context.Context, o any) error {\n\th, ok := o.(*ReleaseRes)\n\tif !ok {\n\t\tslog.Error(\"Expected *ReleaseRes, but got\", slogs.Type, fmt.Sprintf(\"%T\", o))\n\t}\n\n\treturn c.diagnose(h.Release.Info.Status.String())\n}\n\nfunc (Chart) diagnose(s string) error {\n\tif s != \"deployed\" {\n\t\treturn fmt.Errorf(\"chart is in an invalid state\")\n\t}\n\n\treturn nil\n}\n\n// ----------------------------------------------------------------------------\n// Helpers...\n\n// ReleaseRes represents a helm chart resource.\ntype ReleaseRes struct {\n\tRelease *release.Release\n}\n\n// GetObjectKind returns a schema object.\nfunc (ReleaseRes) GetObjectKind() schema.ObjectKind {\n\treturn nil\n}\n","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/derailed/k9s/blob/2d3ccc6ba2ce98c3781bfc441bb3e884f072774f/internal/render/helm/chart.go#L68-L104","documentation":"Chart.diagnose (helm view) returns this when a release's status is anything other than 'deployed' — e.g. pending-install, pending-upgrade, failed, uninstalled, superseded. Caveat: if the passed object is not *ReleaseRes the code logs the type mismatch but keeps going and dereferences a nil Release, which panics — always pass *ReleaseRes.","triggerScenarios":"helm install/upgrade interrupted (pending-upgrade); a release whose hooks or pods failed (failed); listing releases right after upgrade before settle; --wait releases still converging.","commonSituations":"CI pipelines killing helm mid-upgrade leaving pending states; chart hooks failing; rolling back (superseded); timeouts on slow clusters.","solutions":["Inspect state: helm status <release> -n <ns> and helm history <release> -n <ns>","For failed/pending-upgrade: helm rollback <release> <good-revision> or fix values and helm upgrade again","If truly stuck: helm uninstall then reinstall (data loss for stateful workloads — drain first)","Ensure callers pass *ReleaseRes so the nil-deref path cannot trigger"],"exampleFix":"// before: passes the wrong type -> nil deref after the !ok log\nchart.Healthy(ctx, res)\n// after\nif rr, ok := res.(*ReleaseRes); ok {\n    _ = chart.Healthy(ctx, rr)\n}","handlingStrategy":"type-guard","validationCode":"st := h.Release.Info.Status.String()\nif st != \"deployed\" {\n\t// surface 'helm status <release>' instead of failing\n}","typeGuard":"func isReleaseRes(o any) (*ReleaseRes, bool) {\n\trr, ok := o.(*ReleaseRes)\n\treturn rr, ok\n}","tryCatchPattern":"Guard the type first (the library dereferences nil after a failed assertion); then map non-deployed statuses to remediation: rollback for failed, wait for pending.","preventionTips":["Always pass *ReleaseRes to Chart.Healthy — wrong types panic, not error","Run helm with --wait and adequate --timeout so releases settle before listing","Roll back immediately on failed upgrades in CI to avoid superseded/failed clutter"],"tags":["helm","release-status","health"],"backgroundTag":null,"analyzedSha":"2d3ccc6ba2ce98c3781bfc441bb3e884f072774f","analyzedAt":"2026-08-15T16:09:14.432Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}