thedotmack/claude-mem · error · HostObserverUnavailableError

CLAUDE_MEM_HOST_OBSERVER_PORT=${configured} is the claude-me

Error message

CLAUDE_MEM_HOST_OBSERVER_PORT=${configured} is the claude-mem worker port. Point it at your OpenAI-compatible observer instead.

What it means

The claude-mem worker itself listens on a port; if CLAUDE_MEM_HOST_OBSERVER_PORT points at that same port, host mode would route AI traffic back into claude-mem instead of your external observer. resolveHostObserverPort detects configured === workerPort and throws before probing, preventing a self-referential loop.

Source

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

/** Atomically move staged/current credentials into the active provider slot. */

export function resolveHostObserverPort(
  workerPort: string | number | undefined,
  env: NodeJS.ProcessEnv = process.env,
  probe: HostObserverPortProbe = probeHostObserverPortSync,
): string {
  const worker = parsePort(typeof workerPort === 'number' ? workerPort : nonEmptyString(workerPort));
  const configuredRaw = nonEmptyString(env.CLAUDE_MEM_HOST_OBSERVER_PORT);
  if (configuredRaw) {
    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);

View on GitHub (pinned to 8bc631a71a)

Solutions

  1. Point CLAUDE_MEM_HOST_OBSERVER_PORT at the port your external OpenAI-compatible observer actually listens on (e.g. 4141), not the worker port
  2. Unset CLAUDE_MEM_HOST_OBSERVER_PORT so auto-discovery probes 37777/37778 (skipping the worker port automatically)
  3. If your observer IS meant to be reached on another port, start it there first, then rerun install

Example fix

// before
export CLAUDE_MEM_WORKER_PORT=37777
export CLAUDE_MEM_HOST_OBSERVER_PORT=37777
// after
export CLAUDE_MEM_WORKER_PORT=37777
export CLAUDE_MEM_HOST_OBSERVER_PORT=4141
Defensive patterns

Strategy: validation

Validate before calling

const worker = Number(process.env.CLAUDE_MEM_WORKER_PORT);
const observer = Number(process.env.CLAUDE_MEM_HOST_OBSERVER_PORT);
if (worker && observer && worker === observer) {
  throw new Error('CLAUDE_MEM_HOST_OBSERVER_PORT must differ from the worker port');
}

Try / catch

try {
  buildHostObserverSettings(model, settings, env);
} catch (e) {
  if (e instanceof HostObserverUnavailableError && e.message.includes('is the claude-mem worker port')) {
    console.error('Observer port must not equal CLAUDE_MEM_WORKER_PORT; fix CLAUDE_MEM_HOST_OBSERVER_PORT.');
  } else throw e;
}

Prevention

When it happens

Trigger: Setting CLAUDE_MEM_HOST_OBSERVER_PORT equal to the worker port (CLAUDE_MEM_WORKER_PORT setting or the workerPort argument passed to resolveHostObserverPort), then running install with --provider host or buildHostObserverSettings.

Common situations: Copying CLAUDE_MEM_WORKER_PORT into the observer variable by mistake; assuming worker and observer can share a port; scripting the install from settings where both vars are identical.

Related errors


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