fix(cli): report unresolved config interpolations cleanly in manifest validation - #2904
Conversation
… validation gym env validate promises a clean message and no traceback for a bad config, but that only held for the legacy config path. The manifest-backed workload path (_resolve_manifest_composition) called GlobalConfigDictParser.parse() directly, without the InterpolationResolutionError -> ConfigInterpolationError translation set_global_config_dict applies at the CLI's other config-loading boundary (NVIDIA-NeMo#2310). An unresolved ${key} interpolation in a manifest config raised the raw omegaconf exception straight through @exit_cleanly_on_config_error, which only catches ConfigError. Extract the translation into a shared translate_interpolation_error helper and apply it at the manifest-validation boundary too. Fixes NVIDIA-NeMo#2224 Signed-off-by: Amir Fathi <amirfathi.me@gmail.com>
|
/claude review |
|
SHIP — LGTM, no reliability concerns. Pure refactor: the interpolation-error translation block is extracted verbatim from Checks:
Nit (NOTE, author's call): the |
| manifest_path = _asset(tmp_path) | ||
| config_path = manifest_path.with_name("config.yaml") | ||
| config_path.write_text( | ||
| config_path.read_text(encoding="utf-8").replace( |
There was a problem hiding this comment.
This test doesn't check the manifest path, but the legacy path. Please test your code with incomplete manifest instead.
| ) | ||
| ) | ||
| ) | ||
| except InterpolationResolutionError as e: |
There was a problem hiding this comment.
Is this the only place where we had this raw interpolation error? If not, maybe it's worth updating all at once
|
/ok to test a74ea0e |
|
This is a pure extraction: the interpolation-error translation moved out of |
gym env validatepromises a clean message and no traceback for a bad config, but that onlyholds for the legacy config path.
_resolve_manifest_composition(the manifest-backedworkload path
validate_environmentuses) callsGlobalConfigDictParser.parse()directly,without the
InterpolationResolutionError->ConfigInterpolationErrortranslation thatset_global_config_dictapplies at the CLI's other config-loading boundary (#2310). So amanifest referencing an unresolved
${key}interpolation raises the raw omegaconf exceptionstraight through
@exit_cleanly_on_config_error, which only catchesConfigError, and theuser sees a full stack trace instead of the actionable message the CLI ships everywhere else.
Extracted the translation from
set_global_config_dictinto a sharedtranslate_interpolation_errorhelper innemo_gym/global_config.pyand applied it at themanifest-validation boundary too, so both callers raise the same
ConfigInterpolationErrorwith the same actionable message.
Verified in a clean container (python 3.13,
uv sync --extra dev --extra telemetry):test_unresolved_interpolation_is_reported_cleanly_not_as_a_tracebackfails onmainwith a rawomegaconf.errors.InterpolationKeyErrorand passes on this branch.tests/unit_tests/test_environment_validation.pyandtests/unit_tests/test_global_config.pypass in full (152/152).
ruff checkandruff format --diffare clean on the changed files.touched by this change.