Skip to content
Latchkey

Helm "lookup" Returns Empty During template/Dry-Run in CI

Helm’s lookup function queries the live cluster, but it returns an empty value during helm template and helm install --dry-run (no cluster connection in render-only mode). Templates that assume lookup always returns data break in CI rendering.

What this error means

A chart that reads an existing Secret/ConfigMap with lookup renders empty fields (or a nil-pointer error) under helm template/--dry-run, even though the object exists, because lookup is not executed against the cluster in those modes.

helm output
Error: template: chart/templates/secret.yaml:8:14: executing "..." at <.data.password>:
nil pointer evaluating interface {}.password
# lookup "v1" "Secret" ... returned an empty dict during helm template

Common causes

lookup is a no-op in render-only modes

helm template and helm install --dry-run (client) do not talk to the cluster, so lookup returns an empty map/dict. Code that dereferences the result without guarding then fails.

No default for the missing value

Even during a real install, the looked-up object may not exist yet (first install). Without a fallback, the template errors or renders an empty value.

How to fix it

Guard lookup with a default and existence check

Treat an empty lookup as "not found" and fall back, so render-only modes and first installs both work.

templates/secret.yaml
{{- $existing := (lookup "v1" "Secret" .Release.Namespace "api-secret") | default dict }}
password: {{ (get (default dict $existing.data) "password") | default (randAlphaNum 24 | b64enc) }}

Use server-side dry-run when you need real lookups

  1. Run helm template only for static rendering - expect lookup to be empty there.
  2. Use helm install --dry-run=server to exercise lookups against the cluster.
  3. Never rely on lookup for values that must exist at first install; provide defaults.

How to prevent it

  • Always | default dict a lookup result and guard before dereferencing.
  • Reserve lookup for genuinely cluster-dependent values, with fallbacks.
  • Use --dry-run=server when CI validation needs real cluster state.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →