MemPalace/mempalace · error · DaemonError
daemon endpoint not found
Error message
daemon endpoint not found
What it means
DaemonError from _read_endpoint() (mempalace/daemon.py:182): the endpoint.json file under the palace state dir could not be opened or parsed. Both OSError (missing/unreadable file) and json.JSONDecodeError (truncated or corrupt JSON, e.g. after a crash mid-write) are chained into this error. Endpoint discovery is the first step of DaemonClient construction, so no daemon interaction can proceed.
Source
Thrown at mempalace/daemon.py:182
def endpoint_path(palace_path: str) -> Path:
return state_dir(palace_path) / "endpoint.json"
def pid_path(palace_path: str) -> Path:
return state_dir(palace_path) / "pid"
def queue_path(palace_path: str) -> Path:
return state_dir(palace_path) / "queue.sqlite3"
def _read_endpoint(palace_path: str) -> dict[str, Any]:
try:
with open(endpoint_path(palace_path), encoding="utf-8") as fh:
return json.load(fh)
except (OSError, json.JSONDecodeError) as exc:
raise DaemonError("daemon endpoint not found") from exc
def _pid_alive_windows(pid: int) -> bool:
"""Liveness probe for Windows that never sends a console control event.
``os.kill(pid, 0)`` is NOT a harmless existence check on Windows: signal 0
is ``signal.CTRL_C_EVENT``, so Python routes it to
``GenerateConsoleCtrlEvent`` and sends a Ctrl-C to the target's process
group instead of probing the pid. On a process with an attached console
(e.g. a CI runner) that Ctrl-C is delivered back to *this* interpreter and
surfaces as a spurious ``KeyboardInterrupt`` — exactly the hang seen when
``DaemonClient`` polled a same-process endpoint. Probe via the Win32 process
handle API instead, which has no signalling side effects.
"""
import ctypes
from ctypes import wintypes
SYNCHRONIZE = 0x00100000View on GitHub (pinned to 06cb6987f0)
Solutions
- If no daemon is meant to be running, start one via ensure_client/start_daemon instead of constructing DaemonClient directly.
- If a daemon should be running, check the daemon log for a startup crash, then delete the stale endpoint.json and restart.
- If endpoint.json is corrupt (truncated JSON), remove it and restart the daemon to rewrite it atomically.
- Verify state_dir(palace_path) points where you expect (canonical path, no symlinks/moves).
Example fix
# before
client = DaemonClient(palace_path) # endpoint missing/corrupt
# after
client = get_client_if_running(palace_path) # returns None instead of raising when absent
if client is None:
client = start_daemon(palace_path) Defensive patterns
Strategy: try-catch
Validate before calling
from mempalace import daemon
def endpoint_readable(palace_path: str) -> bool:
p = daemon.endpoint_path(palace_path)
try:
json.loads(p.read_text(encoding="utf-8"))
return True
except (OSError, json.JSONDecodeError):
return False Try / catch
from mempalace.daemon import DaemonError, get_client_if_running
client = get_client_if_running(palace_path) # returns None when absent/stale
if client is None:
client = start_daemon(palace_path) Prevention
- Prefer get_client_if_running over raw DaemonClient for discovery.
- Delete stale/corrupt endpoint.json on daemon shutdown failure and restart cleanly.
- Atomic-write JSON state files (write temp + rename) if you create similar files.
When it happens
Trigger: Constructing DaemonClient or calling get_client_if_running when no daemon ever wrote endpoint.json; the daemon crashed while writing the endpoint file leaving partial JSON; the state dir was copied/moved without endpoint.json; reading permissions lost on the state dir.
Common situations: Hook runs on a fresh clone/machine before the first daemon start; a power loss or kill -9 during daemon startup corrupting endpoint.json; manual cleanup of state dirs; get_client_if_running normally converts this to None (daemon not running), so seeing it directly usually means a direct DaemonClient() call or a corrupted-file path.
Related errors
- daemon token not found for {palace_path}
- daemon endpoint missing port
- daemon returned non-JSON response: {raw[:200]!r}
- operator {op!r} not supported by chroma backend
- operator {key!r} not supported by chroma backend
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/7ad433e3046f326e.
Report an issue: GitHub.