2025, Oct 19 05:00

Hydra and OmegaConf: Resolve string interpolation in grouped configs with relative references

Learn why Hydra/OmegaConf interpolation shows ${feat_size} in grouped configs, how lazy resolution works, and when to use relative vs absolute references.

Hydra makes it easy to compose configuration files, but string interpolation can be tricky when you split settings into config groups. A common case is referencing a sibling key inside a grouped config and then seeing the literal interpolation string in the final output instead of the expected resolved value.

Example setup that looks right but doesn’t resolve

Consider a main config that selects a model configuration via a group:

defaults:
  - net: net_a
  - _self_

And the grouped file:

# net/net_a.yaml
feat_size: 106
stages:
  unit_1:
    in_size: ${feat_size}
    emb_size: 64
    out_size: 64

The expectation is that in_size becomes 106. Instead, when printing the composed model config, in_size may appear as the literal "${feat_size}" rather than the number.

What’s actually happening

Interpolation in OmegaConf (used by Hydra) is absolute by default and resolved lazily. Lazy resolution means the string can remain as-is in the printed structure, but the correct value is produced when you access that specific key. Absolute addressing means the path is evaluated from the root of the composed config. Because the grouped file is composed under a node that matches the group name, the absolute location of the value is not feat_size at the root, but under that node. In terms of absolute interpolation, the correct reference would therefore be ${net.feat_size} for this layout.

If you check the concrete value directly, for example by reading stages.unit_1.in_size, you trigger resolution. Printing the whole config may still show the original string, which is why a spot-check of the exact key is more reliable in this scenario.

Fixing it cleanly

You have two compatible ways to make the intent explicit.

The first is to refer to the absolute path from the root, including the group node, such as ${net.feat_size}. This matches the composed structure.

The second, and generally more appropriate in a grouped file, is to use relative interpolation. OmegaConf supports relative references that are independent of the node’s absolute position. In this case, you want to reference a key located in the same mapping, which can be written as:

# net/net_a.yaml
feat_size: 106
stages:
  unit_1:
    in_size: ${...feat_size}
    emb_size: 64
    out_size: 64

Relative interpolation keeps the reference stable even if the config is composed under different paths, avoiding tight coupling to the group name or where that group is attached in the final tree.

Why this knowledge matters

Understanding that interpolation is absolute by default and resolved lazily helps avoid false alarms during inspection. It also clarifies why a root-style ${key} might not resolve inside a grouped file, and why using ${...key} is more resilient. Relative interpolation removes the dependency on the absolute path of the node and makes reorganizing config trees far less error-prone.

Takeaways

When referencing sibling values inside a grouped Hydra config, prefer relative interpolation like ${...feat_size}. If you choose absolute interpolation, include the full path such as ${net.feat_size}. And when validating what Hydra actually resolves, check the specific key value rather than relying only on the string representation of the entire config.

The article is based on a question from StackOverflow by Dan Jackson and an answer by Omry Yadan.