{"record":{"id":"eea308612708bf19","repo":"MemPalace/mempalace","slug":"daemon-token-not-found-for-palace-path","errorCode":null,"errorMessage":"daemon token not found for {palace_path}","messagePattern":"daemon token not found for (.+?)","errorType":"exception","errorClass":"DaemonError","httpStatus":null,"severity":"error","filePath":"mempalace/daemon.py","lineNumber":162,"sourceCode":"\n\ndef ensure_token(palace_path: str) -> str:\n    token_path = state_dir(palace_path) / \"token\"\n    if token_path.exists():\n        token = token_path.read_text(encoding=\"utf-8\").strip()\n        if token:\n            return token\n    token = secrets.token_urlsafe(32)\n    _write_private(token_path, token + \"\\n\")\n    return token\n\n\ndef read_token(palace_path: str) -> str:\n    token_path = state_dir(palace_path) / \"token\"\n    try:\n        return token_path.read_text(encoding=\"utf-8\").strip()\n    except OSError as exc:\n        raise DaemonError(f\"daemon token not found for {palace_path}\") from exc\n\n\ndef endpoint_path(palace_path: str) -> Path:\n    return state_dir(palace_path) / \"endpoint.json\"\n\n\ndef pid_path(palace_path: str) -> Path:\n    return state_dir(palace_path) / \"pid\"\n\n\ndef queue_path(palace_path: str) -> Path:\n    return state_dir(palace_path) / \"queue.sqlite3\"\n\n\ndef _read_endpoint(palace_path: str) -> dict[str, Any]:\n    try:\n        with open(endpoint_path(palace_path), encoding=\"utf-8\") as fh:\n            return json.load(fh)","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/daemon.py#L144-L180","documentation":"DaemonError from read_token() (mempalace/daemon.py:162): it tries to read the shared-secret token file at <state_dir>/token and re-raises any OSError (missing file, permission denied, unreadable) as DaemonError. The token is the bearer credential DaemonClient sends for HTTP auth, so without it the daemon cannot be used from this client.","triggerScenarios":"Calling DaemonClient / get_client_if_running before the daemon has ever started (ensure_token hasn't created the file); running the client as a different OS user than the one that started the daemon (0600-perm token file via _write_private); deleting the palace state directory; a read-only or corrupted state dir.","commonSituations":"First use on a machine where start_daemon was never invoked; mixed-user setups (daemon under your user, hook under another); cleanup scripts that rm -rf the state dir while the daemon still runs; moving the palace directory without its state dir.","solutions":["Start the daemon first with start_daemon(palace_path) (or ensure_client with auto_start=True) so ensure_token creates the token.","Verify the token file exists and is readable: ls -l <state_dir>/token; if permissions are wrong, restart the daemon under the correct user.","If the state dir was deleted or corrupted, stop any running daemon and let ensure_token regenerate the token.","Check the state directory path resolution (canonical_palace_path / state_dir) matches between the writer and reader of the token."],"exampleFix":"# before\nclient = DaemonClient(palace_path)  # DaemonError if never started\n\n# after\nclient = ensure_client(palace_path, auto_start=True)  # starts daemon + ensures token","handlingStrategy":"fallback","validationCode":"from mempalace import daemon\n\ndef token_ready(palace_path: str) -> bool:\n    return (daemon.state_dir(palace_path) / \"token\").is_file()","typeGuard":null,"tryCatchPattern":"from mempalace.daemon import DaemonError, ensure_client\n\ntry:\n    client = DaemonClient(palace_path)\nexcept DaemonError:\n    client = ensure_client(palace_path, auto_start=True)  # start daemon / mint token","preventionTips":["Always bootstrap daemon usage through ensure_client/start_daemon so ensure_token runs first.","Run the daemon and its clients as the same OS user.","Don't delete or move the state directory while a daemon is in use."],"tags":["daemon","auth","filesystem","startup"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}