fix(config): catch draccus DecodingError in CLI parsing - #4106 (#4260)

* Catch draccus DecodingError in CLI parsing, fix #4105

* Add regression test for draccus DecodingError handling

Covers exit code 1, concise single-line stderr message, and no traceback
on invalid typed CLI input, per review feedback on #4106.

* chore(config): try wrap

---------

Co-authored-by: ravindu somawansa <ravindu.somawansa@gmail.com>
This commit is contained in:
Steven Palma
2026-07-31 13:35:36 +02:00
committed by GitHub
parent 1f35876d16
commit af4d15f9ac
+15 -10
View File
@@ -27,6 +27,7 @@ from typing import Any, TypeVar, cast
import draccus import draccus
import yaml # type: ignore[import-untyped] import yaml # type: ignore[import-untyped]
from draccus.utils import DecodingError
from lerobot.utils.utils import has_method from lerobot.utils.utils import has_method
@@ -306,17 +307,21 @@ def wrap(config_path: Path | None = None) -> Callable[[F], F]:
# Also extract path fields from the YAML/JSON config file # Also extract path fields from the YAML/JSON config file
if config_path_cli: if config_path_cli:
config_path_cli = extract_path_fields_from_config(config_path_cli, path_fields) config_path_cli = extract_path_fields_from_config(config_path_cli, path_fields)
if has_method(argtype, "from_pretrained") and config_path_cli: try:
cli_args = filter_arg("config_path", cli_args) if has_method(argtype, "from_pretrained") and config_path_cli:
cfg = argtype.from_pretrained(config_path_cli, cli_args=cli_args)
else:
if config_path_cli:
cli_args = filter_arg("config_path", cli_args) cli_args = filter_arg("config_path", cli_args)
cfg = draccus.parse( cfg = argtype.from_pretrained(config_path_cli, cli_args=cli_args)
config_class=argtype, else:
config_path=config_path_cli or config_path, if config_path_cli:
args=cli_args, cli_args = filter_arg("config_path", cli_args)
) cfg = draccus.parse(
config_class=argtype,
config_path=config_path_cli or config_path,
args=cli_args,
)
except DecodingError as e:
print(f"error: {e}", file=sys.stderr)
sys.exit(1)
response = fn(cfg, *args, **kwargs) response = fn(cfg, *args, **kwargs)
return response return response