Full lesson
Explore the full explanation, examples, and visuals at your own pace.
deployment.yaml env section
This Deployment looks fine, but kubectl apply rejects it. The two env values, FEATURE_ENABLED set to true and PORT set to 8080, trigger an error about failing to unmarshal a bool into a string field. Unmarshal just means converting parsed data into a typed structure. The exact wording varies by version.
env:
- name: FEATURE_ENABLED
value: true
- name: PORT
value: 8080
# kubectl apply (wording varies by version):
# cannot unmarshal bool into Go struct field
# EnvVar...value of type stringTwo checks, in order
Two checks happen, in order. First, the YAML parser, the tool that reads your text, guesses a type for each value. It decides true is a boolean and 8080 is a number. Then the env schema, the API's rulebook for each field, requires a string. The types don't match, so it's rejected.
Same text, different types
Look at the two sides. On the left, the text is unquoted, so the parser tags true as a boolean and 8080 as a number, and the schema gate stops them. On the right, quotes tell the parser to keep the text as text. Now both arrive as strings and pass.
Fixed: quoted values
Here's the fix on the same two variables. FEATURE_ENABLED and PORT are unchanged, except the values now sit inside double quotes. The parser keeps them as text, so the schema check passes and kubectl apply reports the deployment as configured. Single quotes work too for plain strings like these.
env:
- name: FEATURE_ENABLED
value: "true"
- name: PORT
value: "8080"
# kubectl apply -> deployment configuredThe same trap, elsewhere
This trap isn't limited to env. ConfigMap data values must be strings, and so must label and annotation values. Also, older YAML 1.1 parsers may read yes, no, on, and off as booleans. When in doubt, quote them.
- ConfigMap data values must be strings
- Label and annotation values must be strings
- yes, no, on, off may become booleans
Helm: a quieter version
Helm is a tool that templates Kubernetes manifests. In values.yaml, unquoted 1.10 is parsed as the number 1.1. The quote function then renders "1.1", which is a valid string but the wrong version. Quoting in the template can't undo that. Quote "1.10" at its source in values.yaml.
# values.yaml
appVersion: 1.10 # parsed as number 1.1
# templates/deployment.yaml
value: {{ .Values.appVersion | quote }}
# rendered output:
value: "1.1" # valid, but wrong
# fix in values.yaml:
appVersion: "1.10"No error, wrong value
Follow the path left to right. In values.yaml, 1.10 is parsed as the number 1.1, so the trailing zero is already gone. The template renders 1.1, and that's still a valid manifest. Nothing complains, because a correct-looking value passes validation. It gets applied, and the wrong version is what actually deploys.
Which failure would you rather have?
On the left, kubectl apply stops with a red error. Nothing deploys, and you fix the quotes. On the right, the manifest applies cleanly, but the app runs version 1.1 instead of 1.10. The loud error is safer, because it blocks the bad change. The silent one passes every check and surfaces later in production.
The app always receives text
Quoting only fixes the YAML. It doesn't change what your app receives. The env var reaches the container as text, and the app code reads it as a string. If you need a boolean or a number, your code has to parse "true" or "8080" itself. That step always belongs to the app.
Practical takeaways
YAML guesses each value's type first; Kubernetes then demands strings. So quote anything that must be a string, at its source. Before you apply, check the rendered output with helm template or a dry run, and catch the surprise early.
- Quote string values: env, ConfigMap data, labels, annotations
- Quote Helm source values; pipe template output through quote
- Validate rendered manifests before you apply them

