diff --git a/src/lilbee/core/config/model.py b/src/lilbee/core/config/model.py index 6f4b0043d..aaee41ba7 100644 --- a/src/lilbee/core/config/model.py +++ b/src/lilbee/core/config/model.py @@ -966,7 +966,10 @@ def _resolve_defaults(cls, data: Any) -> Any: else: local = find_local_root() data["data_root"] = local if local is not None else default_data_dir() - root = data["data_root"] + # data_root may arrive as a raw string (e.g. from LILBEE_DATA_ROOT); the + # child-path derivations below use ``/``, so coerce to Path first. + root = Path(data["data_root"]) + data["data_root"] = root if data.get("documents_dir") in (None, _UNSET_PATH): data["documents_dir"] = root / "documents" if data.get("data_dir") in (None, _UNSET_PATH): diff --git a/tests/test_config.py b/tests/test_config.py index 7c391100c..7158e4241 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -747,6 +747,17 @@ def test_env_overrides_toml(self, tmp_path) -> None: with mock.patch.dict(os.environ, env, clear=True): assert Config().semantic_chunking is True + def test_data_root_env_var_is_coerced_to_path(self, tmp_path) -> None: + """LILBEE_DATA_ROOT sets the data_root field directly as a string; + deriving the child paths from it must not raise on str / str.""" + env = _clean_env() + env["LILBEE_DATA_ROOT"] = str(tmp_path) + with mock.patch.dict(os.environ, env, clear=True): + c = Config() + assert c.data_root == tmp_path + assert c.documents_dir == tmp_path / "documents" + assert c.data_dir == tmp_path / "data" + class TestTopicThresholdConfig: def test_default_is_0_75(self, tmp_path) -> None: