Move ConfigMismatchError to the store exceptions module

The CLI reports this error, and importing it from the settings repository
pulled lancedb onto the CLI's import path. Deferring the import into cli()
bought nothing, since cli() runs on every invocation: it cost about 1.9
seconds on a cold start, `--help` included.

It now sits beside the other store exceptions, in a module that imports
nothing, and every importer points there.
This commit is contained in:
Yiorgis Gozadinos 2026-08-21 13:14:05 +03:00
parent 95e38e7137
commit 5c9639bbbb
No known key found for this signature in database
11 changed files with 18 additions and 20 deletions

View file

@ -23,6 +23,7 @@ from haiku.rag.config import ( # noqa: E402
from haiku.rag.logging import configure_cli_logging # noqa: E402
from haiku.rag.store.exceptions import ( # noqa: E402
AmbiguousDatabaseError,
ConfigMismatchError,
MigrationRequiredError,
ReadOnlyError,
SourceUnavailableError,
@ -42,10 +43,6 @@ _cli = typer.Typer(
def cli():
# Imported here rather than at module scope: the settings module pulls in
# lancedb, and the CLI's startup must not pay for it.
from haiku.rag.store.repositories.settings import ConfigMismatchError
try:
_cli()
except (

View file

@ -20,6 +20,7 @@ from haiku.rag.converters import get_converter
from haiku.rag.reranking import get_reranker
from haiku.rag.store.engine import Store
from haiku.rag.store.exceptions import (
ConfigMismatchError,
MigrationRequiredError,
ReadOnlyError,
SourceUnavailableError,
@ -30,10 +31,7 @@ from haiku.rag.store.models.document_item import extract_items
from haiku.rag.store.repositories.chunk import ChunkRepository
from haiku.rag.store.repositories.document import DocumentRepository
from haiku.rag.store.repositories.document_item import DocumentItemRepository
from haiku.rag.store.repositories.settings import (
ConfigMismatchError,
SettingsRepository,
)
from haiku.rag.store.repositories.settings import SettingsRepository
from haiku.rag.utils import escape_sql_string, locate_database
if TYPE_CHECKING:

View file

@ -161,7 +161,7 @@ async def _set_embedder(client: "HaikuRAG") -> None:
usable, so just the recorded provider/name are updated. A changed dimension
requires regenerating every embedding via a full rebuild.
"""
from haiku.rag.store.repositories.settings import ConfigMismatchError
from haiku.rag.store.exceptions import ConfigMismatchError
settings_repo = SettingsRepository(client.store)
stored = await settings_repo.get_current_settings()

View file

@ -1,5 +1,6 @@
from .exceptions import (
AmbiguousDatabaseError,
ConfigMismatchError,
MigrationRequiredError,
ReadOnlyError,
SourceUnavailableError,
@ -12,5 +13,6 @@ __all__ = [
"MigrationRequiredError",
"ReadOnlyError",
"AmbiguousDatabaseError",
"ConfigMismatchError",
"SourceUnavailableError",
]

View file

@ -4,6 +4,12 @@ class ReadOnlyError(Exception):
pass
class ConfigMismatchError(Exception):
"""Raised when stored config doesn't match current config."""
pass
class MigrationRequiredError(Exception):
"""Database requires migration. Run 'haiku-rag migrate' to upgrade."""

View file

@ -2,17 +2,12 @@ import json
import logging
from haiku.rag.store.engine import Store
from haiku.rag.store.exceptions import ConfigMismatchError
from haiku.rag.store.schema import SettingsRecord, query_to_pydantic
logger = logging.getLogger(__name__)
class ConfigMismatchError(Exception):
"""Raised when stored config doesn't match current config."""
pass
class SettingsRepository:
"""Repository for Settings operations."""

View file

@ -394,7 +394,7 @@ class TestAppReadVerbsDoNotWrite:
"""A write CLI verb opens writable: drift raises before any write."""
from haiku.rag.app import HaikuRAGApp
from haiku.rag.config import AppConfig
from haiku.rag.store.repositories.settings import ConfigMismatchError
from haiku.rag.store.exceptions import ConfigMismatchError
async with Store(temp_db_path, create=True) as store:
stored_name_before = (

View file

@ -332,7 +332,7 @@ class TestCliConfigMismatchError:
def test_a_config_mismatch_exits_with_its_remedy(self):
"""The message says which database and what to run, so it is worth more
than a traceback."""
from haiku.rag.store.repositories.settings import ConfigMismatchError
from haiku.rag.store.exceptions import ConfigMismatchError
with patch("haiku.rag.cli._cli") as mock_cli:
mock_cli.side_effect = ConfigMismatchError(

View file

@ -645,7 +645,7 @@ class TestMCPClientLifetime:
read-only mode and raises in writable mode. The MCP server no longer
opts out of it for deletion."""
from haiku.rag.config import get_config
from haiku.rag.store.repositories.settings import ConfigMismatchError
from haiku.rag.store.exceptions import ConfigMismatchError
drifted = get_config().model_copy(deep=True)
drifted.embeddings.model.name = "a-different-model"

View file

@ -1059,7 +1059,7 @@ async def test_rebuild_set_embedder_works_on_empty_database(temp_db_path):
async def test_rebuild_set_embedder_raises_on_vector_dim_mismatch(temp_db_path):
"""SET_EMBEDDER refuses when the vector dimension changed — a full rebuild is needed."""
from haiku.rag.config import AppConfig
from haiku.rag.store.repositories.settings import ConfigMismatchError
from haiku.rag.store.exceptions import ConfigMismatchError
async with HaikuRAG(temp_db_path, create=True):
pass

View file

@ -3,7 +3,7 @@ import logging
import pytest
from haiku.rag.config import AppConfig, get_config
from haiku.rag.store.repositories.settings import ConfigMismatchError
from haiku.rag.store.exceptions import ConfigMismatchError
@pytest.mark.asyncio