MemPalace/mempalace · error · DaemonError
daemon endpoint missing port
Error message
daemon endpoint missing port
What it means
DaemonError from DaemonClient.__init__ (mempalace/daemon.py:1110): endpoint.json was read successfully but contains no 'port' key. The endpoint file records where the daemon listens; a port-less file means it was written by an incompatible/older version, was hand-edited, or was truncated in a way that still parses as JSON.
Source
Thrown at mempalace/daemon.py:1110
for stale in (endpoint_path(palace_path), pid_path(palace_path)):
try:
stale.unlink()
except OSError:
pass
for key, value in previous_env.items():
if value is None:
os.environ.pop(key, None)
else:
os.environ[key] = value
class DaemonClient:
def __init__(self, palace_path: str):
self.palace_path = canonical_palace_path(palace_path)
endpoint = _read_endpoint(self.palace_path)
port = endpoint.get("port")
if port is None:
raise DaemonError("daemon endpoint missing port")
# Don't read the token until we trust the endpoint points at a live
# process we started: a stale endpoint whose pid is dead may have its
# port reused by an unrelated process, and we must not send our bearer
# token there.
pid = endpoint.get("pid")
if pid is not None and not _pid_alive(int(pid)):
raise DaemonError("daemon endpoint pid is not alive")
self.token = read_token(self.palace_path)
self.host = endpoint.get("host") or HOST
self.port = int(port)
# The daemon is always on 127.0.0.1, so a request must never go through
# an HTTP proxy. Building an opener with an empty ProxyHandler bypasses
# urllib's proxy discovery entirely. On macOS that discovery
# (urllib.request._scproxy, via the SystemConfiguration framework) runs
# on the first request to any host and is NOT bounded by the per-request
# timeout — on a CI runner with no network it can hang for tens of
# seconds, which looks exactly like the daemon never came up. A no-proxy
# opener is the correct production choice here and also removes that hang.View on GitHub (pinned to 06cb6987f0)
Solutions
- Stop the daemon if any is running, delete the stale endpoint.json in the state dir, and restart so it is rewritten in the current format.
- If you control the endpoint file (tests), always include both 'port' and 'pid' keys.
- Check the daemon log for the startup that produced the file and confirm version match between client and daemon.
Example fix
# before: hand-written endpoint
{"host": "127.0.0.1"}
# after: let the daemon write it (delete stale file and restart)
# {"host": "127.0.0.1", "port": 52341, "pid": 12345} Defensive patterns
Strategy: validation
Validate before calling
import json
from mempalace import daemon
def endpoint_has_port(palace_path: str) -> bool:
try:
return "port" in json.loads(daemon.endpoint_path(palace_path).read_text())
except (OSError, json.JSONDecodeError):
return False Type guard
def is_valid_endpoint(ep: object) -> bool:
return isinstance(ep, dict) and isinstance(ep.get("port"), int) Try / catch
from mempalace.daemon import DaemonError
try:
client = DaemonClient(palace_path)
except DaemonError:
# stale/incompatible endpoint — clear it and restart the daemon
daemon.endpoint_path(palace_path).unlink(missing_ok=True)
client = start_daemon(palace_path) Prevention
- Never hand-edit endpoint.json; delete and let the daemon rewrite it.
- In tests, always write endpoint fixtures with both 'port' and 'pid'.
- Delete state-dir endpoint files after version upgrades.
When it happens
Trigger: A stale endpoint.json from an older daemon version that recorded only host/pid; manual editing of the file; a JSON object like {} left behind by a failed write or test; concurrent format change after upgrade without cleanup.
Common situations: Upgrading MemPalace while an old endpoint.json persists in the state dir; test fixtures writing minimal endpoint files; state dirs shared/copied between machines.
Related errors
- daemon token not found for {palace_path}
- daemon endpoint not found
- writable daemon startup refused: another writer owns local b
- daemon endpoint pid is not alive
- daemon exited during startup with code {proc.returncode}
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/492028e1ffb21611.
Report an issue: GitHub.