diff --git a/omegaconf/base.py b/omegaconf/base.py index bd6921a75..85b075209 100644 --- a/omegaconf/base.py +++ b/omegaconf/base.py @@ -307,7 +307,11 @@ def _select_impl( throw_on_resolution_failure=throw_on_resolution_failure, ) - assert ret is None or isinstance(ret, Container) + if ret is not None and not isinstance(ret, Container): + raise ConfigKeyError( + f"Error trying to access {key}: node `{'.'.join(split[0:i + 1])}` " + f"is not a container and thus cannot contain `{split[i + 1]}``" + ) root = ret if root is None: diff --git a/tests/test_errors.py b/tests/test_errors.py index cbb5199fa..551c952fd 100644 --- a/tests/test_errors.py +++ b/tests/test_errors.py @@ -1121,3 +1121,16 @@ def test_errors(expected: Expected, monkeypatch: Any) -> None: expected.op(cfg) except Exception as e: assert e.__cause__ is None + + +def test_assertion_error(restore_resolvers: Any) -> None: + def assert_false() -> None: + assert False + + # The purpose of this test is to cover the case where an `AssertionError` + # is processed in `format_and_raise()`. Using a resolver to trigger the assertion + # error is just one way of achieving this goal. + OmegaConf.register_resolver("assert_false", assert_false) + c = OmegaConf.create({"trigger": "${assert_false:}"}) + with pytest.raises(AssertionError): + c.trigger diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py index 366c56202..0581aedc5 100644 --- a/tests/test_interpolation.py +++ b/tests/test_interpolation.py @@ -8,6 +8,7 @@ from omegaconf import Container, IntegerNode, Node, OmegaConf, Resolver, ValidationError from omegaconf._utils import _ensure_container +from omegaconf.errors import ConfigKeyError @pytest.mark.parametrize( # type:ignore @@ -106,7 +107,7 @@ def test_merge_with_interpolation() -> None: def test_non_container_interpolation() -> None: cfg = OmegaConf.create(dict(foo=0, bar="${foo.baz}")) - with pytest.raises(AssertionError): + with pytest.raises(ConfigKeyError): cfg.bar