MemPalace/mempalace · error · PalaceNotFoundError
{db_path}
Error message
{db_path} What it means
`PalaceNotFoundError` whose message is just the db file path, raised in `SQLiteExactBackend._connect`. When `create=False`, the backend verifies `palace/<name>.db` exists on disk before connecting; if not, it raises rather than letting sqlite silently create an empty database and mask the missing-palace bug.
Source
Thrown at mempalace/backends/sqlite_exact.py:953
return
handle.closed = True
try:
handle.conn.close()
except Exception:
logger.debug(
"Failed to close stale immutable sqlite_exact reader for %s",
palace_path,
exc_info=True,
)
def _connect(self, palace_path: str, create: bool, *, read_only: bool = False):
if self._closed:
raise BackendClosedError("SQLiteExactBackend has been closed")
if create and read_only:
raise ValueError("sqlite_exact read-only connections cannot create a palace")
db_path = self._db_path(palace_path)
if not create and not os.path.isfile(db_path):
raise PalaceNotFoundError(db_path)
if create:
os.makedirs(palace_path, exist_ok=True)
try:
os.chmod(palace_path, 0o700)
except (OSError, NotImplementedError):
pass
# Hold the registry lock across cache-check + connect + schema init:
# two threads first-opening the same palace must not each create a
# connection (the loser leaked unclosed and outlived close()) nor run
# _init_schema concurrently on a fresh file, which surfaces transient
# "database is locked" errors before WAL mode is established. Only
# first-open pays for the I/O under the lock; cache hits are a dict
# probe.
with self._clients_lock:
if self._closed:
raise BackendClosedError("SQLiteExactBackend has been closed")
clients = self._read_only_clients if read_only else self._clients
cached = clients.get(palace_path)View on GitHub (pinned to 06cb6987f0)
Solutions
- Verify the path: `ls <palace_path>` and check the `*.db` file actually exists where you point the backend.
- If the palace should be created, pass `create=True` (or run the mining command that builds it).
- Use absolute palace paths (or resolve from config) instead of relative paths that shift with cwd.
- Catch PalaceNotFoundError and surface an onboarding/setup hint to the user.
Example fix
# before
handle = backend._connect("~/palaces/alice", create=False) # path typo / not built
# after
palace_path = str(Path.home() / "palaces" / "alice")
if not Path(palace_path, "mempalace.db").is_file():
raise SystemExit(f"palace not found at {palace_path}; run `mempalace mine` first")
handle = backend._connect(palace_path, create=False) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def palace_db_exists(backend, palace_path) -> bool:
return Path(backend._db_path(palace_path)).is_file() Try / catch
try:
col = backend.get_collection(palace, name)
except PalaceNotFoundError as e:
raise SystemExit(f"palace db missing at {e}; run `mempalace mine` first or fix the path") from e Prevention
- Resolve palace paths to absolute paths from one config source at startup.
- Run a build/mine step before any read path on fresh installs.
- Catch PalaceNotFoundError to branch into first-run onboarding.
When it happens
Trigger: Calling any non-create API (get_collection with create=False, delete_collection, a read) against a palace path that has no db file — wrong path, typo in palace name, palace not yet built, or a fresh clone without the data directory.
Common situations: Wrong working directory so the relative palace path resolves elsewhere; first run on a new machine before `mempalace mine` created the palace; renaming/moving the palace directory; CI checkout without the data.
Related errors
- {palace_path}
- {marker_path}
- {label} length {len(value)} does not match ids length {n}
- query requires exactly one of query_texts or query_embedding
- operator {key!r} not supported by sqlite_exact
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/26738d876d5a6d95.
Report an issue: GitHub.