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
- Point CLAUDE_MEM_HOST_OBSERVER_PORT at the port your external OpenAI-compatible observer actually listens on (e.g. 4141), not the worker port
- Unset CLAUDE_MEM_HOST_OBSERVER_PORT so auto-discovery probes 37777/37778 (skipping the worker port automatically)
- 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
- Never copy CLAUDE_MEM_WORKER_PORT into CLAUDE_MEM_HOST_OBSERVER_PORT when templating configs
- Keep the observer on a clearly different port than any claude-mem service
- Script installs should assert the two env vars differ before invoking the CLI
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
- CLAUDE_MEM_HOST_OBSERVER_PORT=${configuredRaw} is not a vali
- CLAUDE_MEM_HOST_OBSERVER_PORT=${configured} is occupied by a
- Invalid CLAUDE_MEM_QUEUE_ENGINE=${raw}; expected sqlite or b
- Invalid CLAUDE_MEM_REDIS_MODE=${value}; expected external, m
- Invalid CLAUDE_MEM_REDIS_PORT=${value}; expected a TCP port
AI-assisted analysis of thedotmack/claude-mem@8bc631a71a (2026-09-09).
Data as JSON: /api/errors/6c9eeb1667c1e14f.
Report an issue: GitHub.