mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
fix(api): point fresh installs at project setup when resolve finds an empty projects table
On a brand-new config dir, model_post_init bootstraps a 'main' default in config.json but the one-shot CLI path never runs the server-lifespan reconciliation that would create its database row, so the first read fails with a bare "Project not found: 'main'" — which reads as a broken install rather than a missing first-run step. When resolution misses and the projects table is empty, the 404 now names the setup command. Follow-up to #974/#985/#987 (which repair the default during project add but cannot help when the first action is a read). Refs #974. Signed-off-by: phernandez <paul@basicmachines.co>
This commit is contained in:
committed by
Paul Hernandez
parent
32a1c208b3
commit
515b2c8365
@@ -320,7 +320,20 @@ async def resolve_project_identifier(
|
||||
)
|
||||
|
||||
if not project:
|
||||
raise HTTPException(status_code=404, detail=f"Project not found: '{data.identifier}'")
|
||||
detail = f"Project not found: '{data.identifier}'"
|
||||
# Trigger: resolution missed and the projects table is empty.
|
||||
# Why: a fresh install bootstraps config.json's default project before any
|
||||
# reconciliation has created database rows (the one-shot CLI never runs
|
||||
# the server lifespan), so the first read fails on the configured
|
||||
# default and the bare not-found message reads as a broken install
|
||||
# rather than a missing first-run step (#974 follow-up).
|
||||
# Outcome: the error names the setup command instead.
|
||||
if not await project_repository.find_all(limit=1, use_load_options=False):
|
||||
detail = (
|
||||
f"{detail}. No projects are set up yet — run "
|
||||
"'basic-memory project add <name> <path>' to create one."
|
||||
)
|
||||
raise HTTPException(status_code=404, detail=detail)
|
||||
|
||||
return ProjectResolveResponse(
|
||||
external_id=project.external_id,
|
||||
|
||||
@@ -445,6 +445,41 @@ async def test_resolve_project_not_found(client: AsyncClient, v2_projects_url):
|
||||
assert "not found" in response.json()["detail"].lower()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_project_not_found_fresh_install_names_setup_command(
|
||||
client: AsyncClient, v2_projects_url, project_repository
|
||||
):
|
||||
"""#974 follow-up: a fresh install fails its first read with a bare not-found.
|
||||
|
||||
config.json bootstraps a "main" default before any reconciliation has created
|
||||
database rows (the one-shot CLI never runs the server lifespan), so resolving
|
||||
the configured default 404s. With an empty projects table the error must point
|
||||
at first-run setup instead of reading like a broken install.
|
||||
"""
|
||||
for project in await project_repository.find_all():
|
||||
await project_repository.delete(project.id)
|
||||
|
||||
response = await client.post(f"{v2_projects_url}/resolve", json={"identifier": "main"})
|
||||
|
||||
assert response.status_code == 404
|
||||
detail = response.json()["detail"]
|
||||
assert detail.startswith("Project not found: 'main'")
|
||||
assert "basic-memory project add" in detail
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_project_not_found_with_projects_keeps_plain_message(
|
||||
client: AsyncClient, test_project: Project, v2_projects_url
|
||||
):
|
||||
"""A miss against a populated projects table stays a plain not-found."""
|
||||
response = await client.post(
|
||||
f"{v2_projects_url}/resolve", json={"identifier": "nonexistent-project"}
|
||||
)
|
||||
|
||||
assert response.status_code == 404
|
||||
assert response.json()["detail"] == "Project not found: 'nonexistent-project'"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_project_empty_identifier(client: AsyncClient, v2_projects_url):
|
||||
"""Test resolving with empty identifier returns 422."""
|
||||
|
||||
Reference in New Issue
Block a user