Helm, Kustomize and GitOps with Argo CD · Helm Charts That Don't Surprise You
Typos in Values That Helm Silently Ignores
A misspelled value falls back to the chart default without any warning; a values schema turns it into an error.
Scenario
Example company: a team sets replicacount: 6 in values-prod.yaml for a launch. The chart reads replicaCount.
What you see in production
Production runs one replica, the chart default. Nothing failed: helm upgrade succeeded, the diff looked small, and the typo sat in a file nobody re-read until the launch traffic arrived.
The naive code
# values-prod.yaml
replicacount: 6 # the chart expects replicaCount
image:
tag: 2.4.0
Reproduce it
Render the chart with the typo, then add a values.schema.json and lint again:
helm create shop > /dev/null && rm -rf shop/templates/tests shop/templates/hpa.yaml shop/templates/httproute.yaml shop/templates/ingress.yaml
printf 'replicacount: 6\n' > values-prod.yaml
echo "--- rendered replicas with the typo: $(helm template shop ./shop -f values-prod.yaml | grep -m1 'replicas:')"
cat > shop/values.schema.json <<'EOF'
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"additionalProperties": false,
"properties": {
"replicaCount": {"type": "integer", "minimum": 1},
"image": {"type": "object"}, "imagePullSecrets": {}, "nameOverride": {}, "fullnameOverride": {},
"serviceAccount": {}, "podAnnotations": {}, "podLabels": {}, "podSecurityContext": {}, "securityContext": {},
"service": {}, "ingress": {}, "httpRoute": {}, "resources": {}, "livenessProbe": {}, "readinessProbe": {},
"autoscaling": {}, "volumes": {}, "volumeMounts": {}, "nodeSelector": {}, "tolerations": {}, "affinity": {}
}
}
EOF
echo "--- helm lint with a schema:"
helm lint ./shop -f values-prod.yaml 2>&1 | grep -E 'ERROR|failed' | head -2 | cut -c1-150
printf 'replicaCount: 6\n' > values-prod.yaml
echo "--- after fixing the key: $(helm template shop ./shop -f values-prod.yaml | grep -m1 'replicas:')"
Output
--- rendered replicas with the typo: replicas: 1 --- helm lint with a schema: [ERROR] values.yaml: - at '': additional properties 'replicacount' not allowed [ERROR] templates/: values don't meet the specifications of the schema(s) in the following chart(s): --- after fixing the key: replicas: 6
Run this on your computer — see “Get Started” for setup.
Root cause
Helm templates read values by path; a key that doesn't exist evaluates to empty and the template's default or the chart's values.yaml applies. Unknown keys in your values file are simply unused. Without a schema, the chart can't tell a typo from an intentional extra key.
The fix
- Ship a
values.schema.jsonwith every chart: types, ranges, required fields and, where practical,additionalProperties: falseat levels you control. - Run
helm lintandhelm template ... | kubeconformin CI for every values file (each environment). - Review rendered diffs (helm-diff plugin, or your GitOps tool's diff) rather than values diffs.
- Prefer fewer, well-named values over exposing every field.
Trade-offs
- Strict schemas (
additionalProperties: false) break when charts add values; version charts and schemas together. - JSON Schema is verbose; generators (helm-schema plugins) help but need review.
Detect it in production
- Rendered replica counts and resources per environment compared with intent (a CI report).
- Values keys that no template reads (lint tooling).
Key points
- Helm ignores unknown values; typos fall back to defaults silently.
- A values.schema.json makes lint, install and upgrade fail on bad values.
- Lint and render every environment's values in CI and review rendered diffs.
Further reading: Chart values schema files · helm lint
Practice questions
What happens to a misspelled key in a Helm values file?
Answer
Nothing reads it, so the template falls back to the chart's default value without any warning.
What does values.schema.json add to a chart?
Answer
A JSON Schema that helm install, upgrade, lint and template validate the merged values against, so wrong types, missing required values or disallowed keys fail early.
Why review rendered manifests instead of values diffs?
Answer
Values interact with templates and defaults; only the rendered YAML shows what will actually change in the cluster.
Open in the app to mark lessons complete, take notes and track your progress.