Helm range without leaving global scope
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Helm templates, range changes the meaning of the dot value. Inside the loop, . becomes the current item, which is why many templates suddenly lose access to .Values, .Chart, or .Release. The fix is to keep a reference to the root context and use it explicitly.
Why Scope Changes Inside range
Helm templates use Go's text templating rules. The current context is stored in .. When you write a range, Helm rebinds . for each element in the collection.
That means this template is fragile:
Inside the loop, . is now a port value like 8080, not the original top-level chart context. So .Values.appName no longer exists there.
Use $ for the Root Context
Helm exposes the original root as $. You can access global values from anywhere in the template by using $.Values, $.Release, or $.Chart.
That is the most direct answer to "how do I range without leaving global scope?" You do not stop scope from changing. You keep a pointer to the global scope and reference it when needed.
Save the Root in a Named Variable
For more complex templates, many chart authors save the root context into a variable for readability.
This becomes especially useful when nested range and with blocks appear in the same file.
Example With Maps and Nested Objects
Suppose values.yaml contains:
A working template could be:
Inside the loop, .name and .port come from the current port item, while $root.Values.appName still reads the global chart value.
with Has the Same Kind of Scope Change
This problem is not unique to range. with also changes the meaning of ..
The same rule applies: use . for the local narrowed object, and use $ or a saved root variable when you need the global context.
When to Use Local Variables
If a value is used repeatedly, store it once.
This avoids long expressions and makes the template easier to review.
Common Pitfalls
A common mistake is assuming range iterates without changing .. In Helm, that assumption breaks many templates immediately.
Another mistake is mixing . and $ carelessly in nested loops. If the template is hard to read, save the root into a named variable and use clear local names.
Chart authors also sometimes try to solve the problem by copying values into each item. That is unnecessary if the only issue is scope. Root references already solve it cleanly.
Summary
- In Helm,
rangerebinds.to the current loop item. - Use
$to access the original root context from inside the loop. - Saving
.into a variable like$rootimproves readability in complex templates. - The same scoping rule applies to
withblocks. - The goal is not to stop scope changes, but to reference the correct scope explicitly.

