From 95c02addd73de6024a246b966b79631256201caa Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Thu, 27 Aug 2026 17:13:12 +0300 Subject: [PATCH] Name a remedy the command being used has `haiku-ingester` reached the client's refusal, which names `sources=[name]`, a Python argument no CLI user can pass. It refuses a configured set itself, with `--db PATH` and the one-ingester-per-database layout. `haiku-rag`'s own refusal now says where each option goes: `--db-name` is global and precedes the command, `--db` follows it. --- haiku_rag_slim/haiku/rag/cli.py | 4 ++-- haiku_rag_slim/haiku/rag/ingester/app.py | 8 ++++++++ tests/ingester/test_cli.py | 17 +++++++++++++++++ tests/test_cli.py | 7 ++++++- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/haiku_rag_slim/haiku/rag/cli.py b/haiku_rag_slim/haiku/rag/cli.py index acf0dcbc..7a97d9ff 100644 --- a/haiku_rag_slim/haiku/rag/cli.py +++ b/haiku_rag_slim/haiku/rag/cli.py @@ -105,8 +105,8 @@ def resolve_scope( if scope.covers_multiple and not covers_set: raise AmbiguousDatabaseError( f"lancedb.databases names {', '.join(sorted(scope.names))}; this " - "command works on a single database: pass --db-name NAME, or " - "--db PATH." + "command works on a single database: pass --db-name NAME before " + "the command, or --db PATH after it" ) return scope diff --git a/haiku_rag_slim/haiku/rag/ingester/app.py b/haiku_rag_slim/haiku/rag/ingester/app.py index 900b8880..b3334b88 100644 --- a/haiku_rag_slim/haiku/rag/ingester/app.py +++ b/haiku_rag_slim/haiku/rag/ingester/app.py @@ -74,11 +74,19 @@ class IngesterApp: def __init__(self, *, config: AppConfig, db_path: Path | None = None): from haiku.rag.client.scope import DatabaseScope + from haiku.rag.store.exceptions import AmbiguousDatabaseError self._config = config # `--db` names the database directly, and nothing stands in for it: a # manufactured default would override a configured `lancedb.uri`. self._scope = DatabaseScope.resolve(config, database_path=db_path) + if self._scope.covers_multiple: + raise AmbiguousDatabaseError( + "haiku-ingester writes one database, and lancedb.databases " + f"names {', '.join(self._scope.names)}; select one with " + "--db PATH, or give each database its own ingester with a " + "configuration naming a single one" + ) self._engine: AsyncEngine | None = None self._jobs: JobRepo | None = None self._sync: SyncStateRepo | None = None diff --git a/tests/ingester/test_cli.py b/tests/ingester/test_cli.py index 5e6fb3d3..395af6ff 100644 --- a/tests/ingester/test_cli.py +++ b/tests/ingester/test_cli.py @@ -525,6 +525,23 @@ class TestPlacingTheIngesterDatabase: assert scope.names == ("docs",) assert not scope.covers_multiple + def test_a_set_is_refused_with_a_remedy_this_command_has(self, tmp_path): + """The client would name `sources=[name]`, a Python argument no CLI user + can pass.""" + from haiku.rag.store.exceptions import AmbiguousDatabaseError + + config = AppConfig( + lancedb=LanceDBConfig( + databases={"a": str(tmp_path / "a"), "b": str(tmp_path / "b")} + ) + ) + + with pytest.raises(AmbiguousDatabaseError) as raised: + self._app(config) + + assert "--db PATH" in str(raised.value) + assert "sources=" not in str(raised.value) + def test_several_configured_databases_exit_cleanly(self, tmp_path, monkeypatch): """No selector names one of a set, so the CLI reports it rather than printing a traceback.""" diff --git a/tests/test_cli.py b/tests/test_cli.py index cf8cee30..757064d5 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -116,9 +116,14 @@ class TestOneDatabaseCommands: def test_a_configured_set_refuses_a_one_database_command(self, monkeypatch): self._install(monkeypatch, alpha="/db/a.lancedb", beta="/db/b.lancedb") - with pytest.raises(AmbiguousDatabaseError, match="alpha, beta"): + with pytest.raises(AmbiguousDatabaseError, match="alpha, beta") as raised: resolve_scope(None) + # `--db-name` is global and `--db` is per-command, so the remedy says + # where each one goes. + assert "--db-name NAME before the command" in str(raised.value) + assert "--db PATH after it" in str(raised.value) + def test_the_refusal_names_the_databases_and_not_their_locations(self, monkeypatch): """A location in an error message travels into logs and terminals; the names exist so it does not have to."""