What's Actually Happening

Helm chart values from values.yaml or custom values files are not being applied during installation or upgrade. Deployed resources use default values instead of custom values, causing configuration drift.

The Error You'll See

Values ignored:

```bash $ helm install my-release my-chart -f custom-values.yaml

# Resources deployed with wrong config: $ kubectl get deployment my-app -o jsonpath='{.spec.replicas}'

1 # Expected 3 from custom-values.yaml ```

Values not overriding defaults:

```bash # In custom-values.yaml: replicaCount: 3

# But deployment still uses: $ helm get values my-release USER-SUPPLIED VALUES: replicaCount: 3 # Shows correct

$ helm get manifest my-release | grep replicas replicas: 1 # But manifest has default ```

Template not using values:

```bash $ helm template my-chart -f custom-values.yaml | grep image:

image: "nginx:latest" # Expected custom image ```

Why This Happens

  1. 1.Value path mismatch - Value path doesn't match template reference
  2. 2.YAML syntax error - Invalid YAML causing file to be ignored
  3. 3.Values not passed - Forgot -f flag or wrong file
  4. 4.Value precedence issue - Values overridden by other sources
  5. 5.Template syntax error - Template not using .Values correctly
  6. 6.Cached values - Previous release values cached

Step 1: Check Helm Release Values

```bash # Get all values for release helm get values my-release --all

# Get user-supplied values only helm get values my-release

# Get values in YAML format helm get values my-release -o yaml

# Get values with computed defaults helm get values my-release --all -o yaml

# Compare to expected values helm get values my-release -o yaml > actual-values.yaml diff custom-values.yaml actual-values.yaml

# Check release history helm history my-release

# Get values from specific revision helm get values my-release --revision 2 ```

Step 2: Verify Values File Syntax

```bash # Validate YAML syntax cat custom-values.yaml | python -m yaml

# Or use yamllint yamllint custom-values.yaml

# Common YAML mistakes: # - Wrong indentation (must be 2 spaces) # - Missing quotes for special characters # - Colon without space after # - Mixing tabs and spaces

# Check indentation cat -A custom-values.yaml | head -20 # Should show spaces (^I = tabs, wrong)

# Validate with helm helm lint my-chart -f custom-values.yaml

# Use --debug to see computed values helm install my-release my-chart -f custom-values.yaml --debug --dry-run ```

Step 3: Check Value Path Structure

```bash # In values.yaml: # parent: # child: # key: value

# In template: # {{ .Values.parent.child.key }}

# Common mistake - wrong path:

# values.yaml: config: database: host: localhost

# WRONG template reference: {{ .Values.database.host }} # Missing config parent

# CORRECT template reference: {{ .Values.config.database.host }}

# Check actual values structure: helm get values my-release --all -o json | jq 'paths'

# Debug in template: debug: {{ .Values | toYaml }} ```

Step 4: Check Values Precedence

```bash # Helm values precedence (lowest to highest): # 1. Chart values.yaml (defaults) # 2. Parent chart values.yaml (if subchart) # 3. User-supplied values file (-f) # 4. Values from --set # 5. Values from --set-file # 6. Values from --set-string # 7. Values from --set-json (highest)

# Check what values are applied: helm get values my-release --all

# Test with debug: helm template my-chart \ -f custom-values.yaml \ --set key1=value1 \ --debug

# If -f values overridden by --set: # --set takes precedence

# Multiple -f files (later overrides earlier): helm install my-release my-chart \ -f values.yaml \ -f custom-values.yaml \ -f production-values.yaml # This wins

# Check specific value: helm get values my-release -o jsonpath='{.replicaCount}' ```

Step 5: Debug Template Rendering

```bash # Render templates without installing helm template my-chart -f custom-values.yaml

# Render specific template helm template my-chart -f custom-values.yaml -s templates/deployment.yaml

# Debug with verbose output helm template my-chart -f custom-values.yaml --debug

# Check computed values helm template my-chart -f custom-values.yaml | grep -A 5 "replicas"

# Use helm pull to inspect chart helm pull my-chart --untar --untardir ./chart-inspect cat ./chart-inspect/my-chart/values.yaml

# Test template rendering helm install my-release my-chart -f custom-values.yaml --dry-run --debug ```

Step 6: Check for Global Values Issues

```yaml # Global values must use .Values.global

# In values.yaml: global: imageRegistry: my-registry.com

# In template: # WRONG: image: {{ .Values.imageRegistry }}/my-app

# CORRECT: image: {{ .Values.global.imageRegistry }}/my-app

# For subcharts, global values are shared: # Parent values.yaml: global: imageRegistry: my-registry.com

# Subchart can access: # {{ .Values.global.imageRegistry }}

# Non-global values are NOT shared to subcharts: # Parent: database: host: db-server # Not visible to subcharts

# Subchart values.yaml: database: host: localhost # Subchart uses its own ```

Step 7: Fix Value Merging Issues

```yaml # Helm merges values deeply, but lists are replaced entirely

# Default values.yaml: config: ports: - 80 - 443

# Custom values.yaml: config: ports: - 8080

# Result: ports = [8080] (list replaced, not merged!)

# To preserve and add: # Use null to remove: config: ports: - null # Remove 80 - null # Remove 443 - 8080 - 8443

# Or specify full list: config: ports: - 80 - 443 - 8080

# For maps, values are merged: # Default: config: database: host: localhost port: 5432

# Custom: config: database: host: prod-db

# Result: # config.database.host = prod-db # config.database.port = 5432 (preserved) ```

Step 8: Check Chart Dependencies

```bash # Check chart dependencies helm dependency list my-chart

# Update dependencies helm dependency update my-chart

# Build dependencies helm dependency build my-chart

# Check subchart values cat my-chart/charts/subchart/values.yaml

# Subchart values can be overridden: # In parent values.yaml: subchart: enabled: true config: key: value

# The subchart name must match ```

Step 9: Force Refresh Values

```bash # Force helm to refresh values:

# Option 1: Uninstall and reinstall helm uninstall my-release helm install my-release my-chart -f custom-values.yaml

# Option 2: Upgrade with reset-values helm upgrade my-release my-chart -f custom-values.yaml --reset-values

# --reset-values clears cached values and uses only provided values

# Option 3: Force resource replacement helm upgrade my-release my-chart -f custom-values.yaml --force

# Check upgrade changes helm upgrade my-release my-chart -f custom-values.yaml --dry-run

# Verify values applied helm get values my-release --all ```

Step 10: Monitor and Validate Deployments

```bash # Create validation script cat << 'EOF' > validate_helm_values.sh #!/bin/bash RELEASE=my-release NAMESPACE=default

echo "=== Release Values ===" helm get values $RELEASE --all -o yaml

echo "" echo "=== Expected vs Actual Replicas ===" EXPECTED=$(helm get values $RELEASE -o jsonpath='{.replicaCount}') ACTUAL=$(kubectl get deployment -n $NAMESPACE -l app.kubernetes.io/instance=$RELEASE -o jsonpath='{.items[0].spec.replicas}') echo "Expected: $EXPECTED" echo "Actual: $ACTUAL"

echo "" echo "=== Image Check ===" EXPECTED_IMAGE=$(helm get values $RELEASE -o jsonpath='{.image.repository}'):$(helm get values $RELEASE -o jsonpath='{.image.tag}') ACTUAL_IMAGE=$(kubectl get deployment -n $NAMESPACE -l app.kubernetes.io/instance=$RELEASE -o jsonpath='{.items[0].spec.template.spec.containers[0].image}') echo "Expected: $EXPECTED_IMAGE" echo "Actual: $ACTUAL_IMAGE"

echo "" echo "=== Release History ===" helm history $RELEASE EOF

chmod +x validate_helm_values.sh

# Run validation ./validate_helm_values.sh

# Use helm diff plugin helm plugin install https://github.com/databus23/helm-diff helm diff upgrade my-release my-chart -f custom-values.yaml ```

Helm Values Application Checklist

CheckCommandExpected
Values syntaxyamllintValid YAML
Values passedhelm get valuesShows custom values
Template refsgrep .ValuesCorrect path
Precedencehelm templateCorrect override
Merginghelm get values --allExpected merged values
Dry runhelm install --dry-runMatches expected

Verify the Fix

```bash # After fixing value application

# 1. Check values are passed helm get values my-release -o yaml // Shows custom values

# 2. Verify manifest has correct values helm get manifest my-release | grep -E "replicas|image:" // Shows expected values

# 3. Check deployed resources kubectl get deployment my-app -o yaml | grep -E "replicas|image:" // Matches custom values

# 4. Compare to values file diff <(helm get values my-release -o yaml) custom-values.yaml // Should match or have expected differences

# 5. Test upgrade applies new values helm upgrade my-release my-chart -f updated-values.yaml --dry-run // Shows changes in diff

# 6. Verify release history helm history my-release // Shows upgrade with new values ```

  • [Fix Helm Chart Template Render Failed](/articles/fix-helm-chart-template-render-failed)
  • [Fix Helm Release Failed](/articles/fix-helm-release-failed)
  • [Fix Helm Chart Dependency Missing](/articles/fix-helm-chart-dependency-missing)