Helm’s template rendering is failing because the Go templating engine is encountering issues processing your Chart’s templates/ directory, usually due to syntax errors or logical inconsistencies that prevent a valid Kubernetes manifest from being generated.
Common Causes and Fixes
-
Syntax Errors in Go Templates:
-
Diagnosis: Run
helm template <release-name> <chart-path> --debug. Look for lines near the top of the output that mentionerror evaluating templateand indicate a specific file and line number. Common errors include missing closing braces}}, incorrect quoting, or misplaced delimiters. -
Fix: Carefully examine the specified file and line number. For example, if you have
{{ .Values.myValue }and it should be{{ .Values.myValue }}(a missing closing brace), correct it to{{ .Values.myValue }}. The Go template engine expects precise syntax. -
Why it works: Correcting the syntax allows the Go template engine to parse the template file correctly, resolving the immediate parsing error.
-
-
Undefined Values or Variables:
- Diagnosis: The error message will often say
(zero value)orundefinedwhen trying to access a value. For instance,template: mychart/templates/deployment.yaml:15:14: executing "mychart/templates/deployment.yaml" at <.Values.nonExistentKey>: nil pointer evaluating Values.nonExistentKey. - Fix:
-
Check your
values.yamlfile to ensure the key exists. -
If it’s a conditional value, ensure the condition is met.
-
In your template, use
{{ .Values.myKey | default "defaultValue" }}to provide a fallback. -
If the value is expected to be set via
--setor avalues.yamlfile, verify that it’s being provided.
-
- Why it works: Providing a default value or ensuring the value is actually defined prevents the template engine from attempting to dereference a
nilor non-existent object, which causes a panic.
- Diagnosis: The error message will often say
-
Incorrect
rangeLoop Syntax or Usage:-
Diagnosis: Errors like
template: mychart/templates/configmap.yaml:5:14: executing "mychart/templates/configmap.yaml" at <range .Values.items>: range can't iterate over nilorinvalid index in rangeindicate a problem with iterating over a list or map. -
Fix: Ensure the variable you’re ranging over is actually a list or map. If it might be
nilor empty, add a check:{{ if .Values.items }} {{ range .Values.items }} - key: {{ .key }} value: {{ .value }} {{ end }} {{ else }} # Handle case where items is empty or nil {{ end }}Also, confirm that the structure of the data you’re ranging over matches your template’s expectations (e.g., if you expect
{{ .key }}and{{ .value }}, then.Values.itemsmust be a list of maps, each withkeyandvaluefields). -
Why it works: The
ifcondition explicitly checks if the iterable exists and is notnilbefore attempting torangeover it, preventing the panic.
-
-
Issues with
includeortemplateFunctions:- Diagnosis: Errors might look like
template: mychart/templates/service.yaml:3:1: executing "mychart/templates/service.yaml" at <include>: template "mychart/templates/_helpers.tpl" not foundorfunction "myFunction" not defined. - Fix:
- Ensure the referenced template file exists in your
templates/directory or a subdirectory that’s part of the chart. - Verify the name passed to
includeortemplateexactly matches the name of the partial template (usually the filename without.yaml). For partials, the name is often derived from its path relative to the_helpers.tplor thetemplates/directory. For example,_helpers.tplis typically accessed as"mychart/templates/_helpers.tpl". - Check that custom functions are correctly defined in a
_helpers.tplfile and registered.
- Ensure the referenced template file exists in your
- Why it works: The
includeandtemplatefunctions rely on Helm’s internal registry of available templates. If a template isn’t found or named correctly, the function call fails.
- Diagnosis: Errors might look like
-
Incorrect Handling of Namespaces or Release Names:
- Diagnosis: Errors can arise when trying to reference the release name or namespace dynamically, especially if they are not correctly scoped or passed. For example, using
.Release.Namein a context where it’s not available or expecting a different value. - Fix: Ensure you are using the correct global template variables:
.Release.Name: The name of the Helm release..Release.Namespace: The namespace the release is deployed into..Chart.Name: The name of the chart..Chart.Version: The version of the chart. When defining resources, it’s common to use these:
If you’re passing these values down to partials, ensure they are correctly passed as arguments.metadata: name: {{ .Release.Name }}-{{ include "mychart.fullname" . }} namespace: {{ .Release.Namespace }} - Why it works: These are predefined variables available within the Helm templating context. Using them correctly allows Helm to inject the appropriate runtime information into your Kubernetes manifests.
- Diagnosis: Errors can arise when trying to reference the release name or namespace dynamically, especially if they are not correctly scoped or passed. For example, using
-
Type Mismatches in Comparisons or Operations:
-
Diagnosis: Errors like
template: mychart/templates/ingress.yaml:10:10: executing "mychart/templates/ingress.yaml" at <eq .Port 80>: can't evaluate field Port in type stringindicate you’re trying to compare or operate on values of incompatible types (e.g., comparing a string to an integer, or expecting an object when you have a string). -
Fix: Use the
typeOffunction for debugging:{{ typeOf .Values.myValue }}. Then, ensure the types match. You might need to explicitly convert types, for example:-
To convert a string to an integer:
{{ .Values.myStringPort | int }} -
To convert an integer to a string:
{{ .Values.myIntPort | toString }} -
To check if a value is a map:
{{ if eq (typeOf .Values.myMap) "map" }}
-
-
Why it works: Go templates are strongly typed. Explicitly ensuring that data types are consistent for comparisons and operations prevents runtime type errors.
-
The next error you might encounter after fixing template rendering issues is a helm install or helm upgrade failure due to invalid Kubernetes API objects, which occurs when the rendered YAML is syntactically correct but doesn’t conform to the Kubernetes API schema for the specified resource type.