Skip to content

Commit aeaaaa6

Browse files
phernandezclaude
andcommitted
fix(core): seed a default project for fresh local Postgres
BasicMemoryConfig.model_post_init skipped default-project seeding whenever the backend was Postgres, using the backend as a proxy for 'cloud mode'. That left a fresh LOCAL Postgres with no default project, so create_memory_project raised 'No default project configured'. Gate the skip on skip_initialization_sync (set by for_cloud_tenant) instead, so stateless/cloud still skips while local Postgres seeds 'main' like SQLite. SQLite and cloud behavior are unchanged. Tests cover both branches. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: phernandez <paul@basicmachines.co>
1 parent 9494f3f commit aeaaaa6

2 files changed

Lines changed: 33 additions & 3 deletions

File tree

src/basic_memory/config.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -748,9 +748,14 @@ def get_project_path(self, project_name: Optional[str] = None) -> Path: # pragm
748748

749749
def model_post_init(self, __context: Any) -> None:
750750
"""Ensure configuration is valid after initialization."""
751-
# Skip project initialization in cloud mode - projects are discovered from DB
752-
if self.database_backend == DatabaseBackend.POSTGRES: # pragma: no cover
753-
return # pragma: no cover
751+
# Skip default-project seeding only for stateless/cloud deployments, where
752+
# projects are discovered from the database per tenant (for_cloud_tenant
753+
# sets skip_initialization_sync=True). Gating on the *backend* was wrong:
754+
# a LOCAL Postgres backend still needs a default project seeded like SQLite,
755+
# so a fresh local Postgres had no default project and create_memory_project
756+
# raised "No default project configured" (benchmarks write-load doc).
757+
if self.skip_initialization_sync:
758+
return
754759

755760
# Trigger: no projects configured (fresh install or empty config)
756761
# Why: every config needs at least one project to be functional

tests/test_config.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,31 @@ def test_model_post_init_fallback_without_basic_memory_home(self, config_home, m
124124
assert Path(config.projects["other"].path) == other_path
125125
assert config.default_project == "other"
126126

127+
def test_model_post_init_seeds_default_for_local_postgres(self, config_home, monkeypatch):
128+
"""A LOCAL Postgres backend still seeds a default project, like SQLite.
129+
130+
The seeding skip is for stateless/cloud (skip_initialization_sync), not the
131+
Postgres backend — otherwise a fresh local Postgres has no default project
132+
and create_memory_project raises "No default project configured".
133+
"""
134+
monkeypatch.delenv("BASIC_MEMORY_HOME", raising=False)
135+
136+
config = BasicMemoryConfig(database_backend="postgres")
137+
138+
assert "main" in config.projects
139+
assert config.default_project == "main"
140+
141+
def test_model_post_init_skips_seeding_for_stateless_deployments(
142+
self, config_home, monkeypatch
143+
):
144+
"""Stateless/cloud configs discover projects from the DB, so seed nothing."""
145+
monkeypatch.delenv("BASIC_MEMORY_HOME", raising=False)
146+
147+
config = BasicMemoryConfig(database_backend="postgres", skip_initialization_sync=True)
148+
149+
assert config.projects == {}
150+
assert config.default_project is None
151+
127152
def test_basic_memory_home_with_relative_path(self, config_home, monkeypatch):
128153
"""Test that BASIC_MEMORY_HOME works with relative paths."""
129154
relative_path = "relative/memory/path"

0 commit comments

Comments
 (0)