MemPalace/mempalace · error · DaemonError

daemon is not running; job {args.job_id} is {job['state']}

Error message

daemon is not running; job {args.job_id} is {job['state']}

What it means

Raised by the CLI job 'wait' fallback path when the daemon is not running but the job still exists in the persisted queue store in a non-terminal state (not in TERMINAL_STATES). Because no daemon is alive to advance the job, waiting is impossible, so the CLI refuses rather than hang. The message includes the job id and its current state (e.g. 'queued' or 'running').

Source

Thrown at mempalace/cli.py:1300

                    jobs = [
                        job_to_dict(job, include_payload=False)
                        for job in QueueStore(qpath).list(args.limit)
                    ]
            for job in jobs:
                print(f"{job['id']}  {job['state']:<9}  {job['kind']:<10}  {job['created_at']}")
            return

        if action == "wait":
            client = get_client_if_running(palace_path)
            if client is not None:
                job = client.wait(args.job_id)
            else:
                qpath = queue_path(palace_path)
                if not qpath.exists():
                    raise DaemonError("daemon is not running")
                job = job_to_dict(QueueStore(qpath).get(args.job_id))
                if job.get("state") not in TERMINAL_STATES:
                    raise DaemonError(f"daemon is not running; job {args.job_id} is {job['state']}")
            result = job.get("result") or {}
            from .service import print_job_result

            exit_code = print_job_result(result)
            if job.get("state") != "succeeded" and exit_code == 0:
                print(f"mempalace: daemon job failed: {job.get('error')}", file=sys.stderr)
                exit_code = 1
            if exit_code:
                sys.exit(exit_code)
            return
    except DaemonError as exc:
        print(f"mempalace: daemon error: {exc}", file=sys.stderr)
        sys.exit(1)


def cmd_search(args):
    from .searcher import search, SearchError

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Restart the daemon so it resumes processing the queue, then re-run wait
  2. Inspect the job state with the list action to decide whether to cancel/retry the stuck job
  3. If the daemon is crashing repeatedly, check daemon logs for the underlying failure before retrying
  4. If the job is wedged in a non-terminal state and the daemon will not resume it, cancel or re-enqueue it

Example fix

# before
mempalace job wait abc123   # -> daemon is not running; job abc123 is running

# after
mempalace daemon start   # daemon resumes the queue
mempalace job wait abc123
Defensive patterns

Strategy: retry

Validate before calling

client = get_client_if_running(palace_path)
if client is None:
    job = job_to_dict(QueueStore(queue_path(palace_path)).get(job_id))
    if job.get("state") not in TERMINAL_STATES:
        # daemon died mid-job: restart it instead of waiting
        start_daemon()  # resumes the queue
        client = get_client_if_running(palace_path)

Try / catch

try:
    wait_job(job_id)
except DaemonError as exc:
    if "is" in str(exc) and str(exc).split()[-1] in {"queued", "running"}:
        restart_daemon_and_wait_again(job_id)  # one bounded retry
    else:
        raise

Prevention

When it happens

Trigger: Running the job wait action when get_client_if_running() returns None (daemon down), queue_path(palace_path) exists, QueueStore.get(job_id) succeeds, but job['state'] is not a terminal state — i.e. the daemon died or was stopped mid-job.

Common situations: Daemon crashed or was killed while a job was queued/running; machine rebooted mid-job; user manually stopped the daemon then tried to wait on the in-flight job; stale queue left behind after an unclean shutdown.

Related errors


AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15). Data as JSON: /api/errors/5d02bd6bcbe31688. Report an issue: GitHub.