thedotmack/claude-mem · error · HostObserverUnavailableError

CLAUDE_MEM_HOST_OBSERVER_PORT=${configured} has nothing list

Error message

CLAUDE_MEM_HOST_OBSERVER_PORT=${configured} has nothing listening. Start your OpenAI-compatible observer on that port, then rerun with --provider host.

What it means

If CLAUDE_MEM_HOST_OBSERVER_PORT is set and explicitly given, claude-mem never falls back to default candidate ports: whatever the probe reports other than 'observer' throws. 'free' (nothing listening, bind test succeeds) produces this error telling you to actually start the observer.

Source

Thrown at src/npx-cli/cmem-memory-credentials.ts:253

    const configured = parsePort(configuredRaw);
    if (configured == null) {
      throw new HostObserverUnavailableError(
        `CLAUDE_MEM_HOST_OBSERVER_PORT=${configuredRaw} is not a valid port. Set it to the port your OpenAI-compatible observer already listens on.`,
      );
    }
    if (worker != null && configured === worker) {
      throw new HostObserverUnavailableError(
        `CLAUDE_MEM_HOST_OBSERVER_PORT=${configured} is the claude-mem worker port. Point it at your OpenAI-compatible observer instead.`,
      );
    }
    const status = probe(configured);
    if (status === 'observer') return String(configured);
    if (status === 'occupied') {
      throw new HostObserverUnavailableError(
        `CLAUDE_MEM_HOST_OBSERVER_PORT=${configured} is occupied by a process that is not an OpenAI-compatible observer. Stop that process or point CLAUDE_MEM_HOST_OBSERVER_PORT at your observer.`,
      );
    }
    throw new HostObserverUnavailableError(
      `CLAUDE_MEM_HOST_OBSERVER_PORT=${configured} has nothing listening. Start your OpenAI-compatible observer on that port, then rerun with --provider host.`,
    );
  }

  const candidates = hostObserverCandidatePorts(workerPort, env);
  for (const port of candidates) {
    const status = probe(port);
    if (status === 'observer') return String(port);
  }

  throw new HostObserverUnavailableError(
    `No OpenAI-compatible host observer is listening on 127.0.0.1:${candidates.join(' or ') || HOST_OBSERVER_DEFAULT_PORT}. Host mode uses an observer you already run; claude-mem does not start one. Start your observer, then rerun with --provider host. If it uses another port, set CLAUDE_MEM_HOST_OBSERVER_PORT.`,
  );
}

export function buildHostObserverSettings(
  observerModel: 'cursor' | 'grok-bot',
  settings: SettingsLike,

View on GitHub (pinned to 8bc631a71a)

Solutions

  1. Start your OpenAI-compatible observer so it listens on the configured port, then rerun the install with --provider host
  2. Verify it is up: curl http://127.0.0.1:$CLAUDE_MEM_HOST_OBSERVER_PORT/v1/models
  3. If the observer runs on a different port, update CLAUDE_MEM_HOST_OBSERVER_PORT to match
  4. Unset CLAUDE_MEM_HOST_OBSERVER_PORT to fall back to auto-probing 37777/37778

Example fix

// before
export CLAUDE_MEM_HOST_OBSERVER_PORT=4141  # nothing listening
npx claude-mem install --provider host
// after
start-my-observer --port 4141
export CLAUDE_MEM_HOST_OBSERVER_PORT=4141
npx claude-mem install --provider host
Defensive patterns

Strategy: validation

Validate before calling

const port = process.env.CLAUDE_MEM_HOST_OBSERVER_PORT;
if (port) {
  const up = await fetch(`http://127.0.0.1:${port}/v1/models`).then(r => r.ok).catch(() => false);
  if (!up) throw new Error(`Observer not listening on ${port}; start it before installing`);
}

Try / catch

try {
  const port = resolveHostObserverPort(workerPort, env);
} catch (e) {
  if (e instanceof HostObserverUnavailableError && e.message.includes('has nothing listening')) {
    // start the observer, then retry the install
  } else throw e;
}

Prevention

When it happens

Trigger: resolveHostObserverPort with CLAUDE_MEM_HOST_OBSERVER_PORT set to a valid port on which no process is listening (probe returns 'free'), while running install with --provider host.

Common situations: Observer crashed or was never started; firewall/container isolation makes loopback unreachable; wrong port typo'd to an unused number; observer only bound to a non-loopback interface.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@8bc631a71a (2026-09-09). Data as JSON: /api/errors/e6947f4b586b9e03. Report an issue: GitHub.