From af4d15f9acfb589d2fb8aa9ac4eb404416707196 Mon Sep 17 00:00:00 2001 From: Steven Palma Date: Fri, 31 Jul 2026 13:35:36 +0200 Subject: [PATCH] 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 --- src/lerobot/configs/parser.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/lerobot/configs/parser.py b/src/lerobot/configs/parser.py index 46cff2b48..b170b69a0 100644 --- a/src/lerobot/configs/parser.py +++ b/src/lerobot/configs/parser.py @@ -27,6 +27,7 @@ from typing import Any, TypeVar, cast import draccus import yaml # type: ignore[import-untyped] +from draccus.utils import DecodingError 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 if config_path_cli: config_path_cli = extract_path_fields_from_config(config_path_cli, path_fields) - if has_method(argtype, "from_pretrained") and config_path_cli: - cli_args = filter_arg("config_path", cli_args) - cfg = argtype.from_pretrained(config_path_cli, cli_args=cli_args) - else: - if config_path_cli: + try: + if has_method(argtype, "from_pretrained") and config_path_cli: 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, - ) + cfg = argtype.from_pretrained(config_path_cli, cli_args=cli_args) + else: + if config_path_cli: + 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) return response