# Helm Debugging Tips
## Rendering and Validation
### Dry-run with debug output
```bash
helm install myapp ./mychart --dry-run --debug
```
This renders templates locally without installing, showing you the exact manifests that would be deployed.
### Template rendering only
```bash
helm template myapp ./mychart --debug
```
Useful for piping output to other tools or grepping for specific values.
### Helm Template vs Helm Install Dry-Run: Key Differences
#### `helm template`
- **Runs locally** - doesn't connect to Kubernetes API
- **No cluster validation** - can't check if resources would actually work
- **No release creation** - doesn't create a release object
- **Faster** - no network calls
- **Works offline** - doesn't need a cluster connection
- **Can't use `lookup` function** - since there's no cluster to query
#### `helm install --dry-run --debug`
- **Connects to cluster** - communicates with Kubernetes API server
- **Validates resources** - checks if API versions exist, CRDs are installed, etc.
- **Creates release (in memory)** - simulates the full release process
- **Checks RBAC** - validates permissions
- **Slower** - network overhead
- **Requires cluster access**
- **Can use `lookup` function** - queries live cluster data
#### When to Use Each
**Use `helm template` when:**
- You want quick feedback on template rendering
- You're working offline or don't have cluster access
- You want to pipe output to other tools (kubectl, yq, etc.)
- You're debugging pure template logic issues
- You want to see rendered manifests without any cluster interaction
**Use `helm install --dry-run --debug` when:**
- You want to validate against actual cluster state
- You need to test RBAC permissions
- Your templates use the `lookup` function
- You want to catch API version mismatches
- You're doing final validation before actual deployment
- You want to see exactly what would happen during installation
-
### Validate against a live cluster
```bash
helm install myapp ./mychart --dry-run --debug --validate
```
This performs server-side validation, catching issues like missing CRDs or API versions.
## Inspecting Releases
### Get all values (computed + defaults)
```bash
helm get values myapp --all
```
Shows the complete merged values, not just what you overrode.
### See the actual manifests deployed
```bash
helm get manifest myapp
```
Shows exactly what's running in your cluster, useful for comparing with what you expected.
### Check release history
```bash
helm history myapp
```
See all revisions and their statuses.
## Advanced Template Debugging
### Use `fail` function for complex sanity checks
```yaml
{{- if and not .Values.image.tag not eq .Values.image.tag "latest" }}
{{- fail "image.tag is required, it may not be set to latest" }}
{{- end }}
```
### Debug specific template files
```bash
helm template myapp ./mychart -s templates/deployment.yaml
```
The `-s` flag renders only specific templates.
### Inspect computed values in templates
```yaml
{{ toYaml .Values }}
```
Temporarily add this to see the full values structure.
## Troubleshooting Failed Installs
### Check release status (in all namespaces)
```bash
helm list -A
helm status myapp
```
### Force delete stuck releases
```bash
helm delete myapp --no-hooks
kubectl delete secret -n <namespace> sh.helm.release.v1.myapp.v<number>
```
### Disable hooks for debugging
```bash
helm install myapp ./mychart --no-hooks
```
Hooks can cause mysterious failures; this bypasses them.
## Linting and Best Practices
### Comprehensive lint
```bash
helm lint ./mychart --strict --with-subcharts
```
Catches template errors, warning and chart structure issues.
### Use values schema (values.schema.json)
Define a JSON schema to validate user-provided values at install time.
## Pro Tips
1. **Use `--create-namespace`** to avoid "namespace not found" errors
2. **Keep `_helpers.tpl` clean** - complex logic there is hard to debug
3. **Use `lookup` function carefully** - it queries the cluster during rendering and can cause unexpected behavior
4. **Enable verbose output** with `-v` flag (up to `-vvv` for maximum verbosity)
5. **Test with different Kubernetes versions** using `--kube-version` flag in dry-run mode
## Additional Resources
- [Helm Documentation](https://helm.sh/docs/)
- [Helm Template Language](https://helm.sh/docs/chart_template_guide/)
- [Debugging Charts](https://helm.sh/docs/chart_template_guide/debugging/)