thedotmack/claude-mem · error · HostObserverUnavailableError
CLAUDE_MEM_HOST_OBSERVER_PORT=${configuredRaw} is not a vali
Error message
CLAUDE_MEM_HOST_OBSERVER_PORT=${configuredRaw} is not a valid port. Set it to the port your OpenAI-compatible observer already listens on. What it means
Host observer mode reuses an OpenAI-compatible HTTP server already running on your machine; you point it there via CLAUDE_MEM_HOST_OBSERVER_PORT. Before probing, resolveHostObserverPort parses the variable with parsePort, and any value that is not a plain valid port number (1-65535) makes the install fail fast with this HostObserverUnavailableError so a typo'd URL, protocol prefix, or empty string never gets probed.
Source
Thrown at src/npx-cli/cmem-memory-credentials.ts:237
};
}
return null;
}
/** 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.`,
);View on GitHub (pinned to 8bc631a71a)
Solutions
- Set CLAUDE_MEM_HOST_OBSERVER_PORT to the bare integer port your observer listens on, e.g. export CLAUDE_MEM_HOST_OBSERVER_PORT=4141
- Unset the variable entirely (unset CLAUDE_MEM_HOST_OBSERVER_PORT) to let claude-mem auto-probe default ports 37777/37778
- Verify the value is a decimal number in 1-65535 with no scheme, slashes, or spaces, then rerun the install with --provider host
Example fix
// before export CLAUDE_MEM_HOST_OBSERVER_PORT=http://127.0.0.1:4141 // after export CLAUDE_MEM_HOST_OBSERVER_PORT=4141
Defensive patterns
Strategy: validation
Validate before calling
const raw = process.env.CLAUDE_MEM_HOST_OBSERVER_PORT;
if (raw) {
const port = Number(raw);
if (!Number.isInteger(port) || port < 1 || port > 65535) {
throw new Error(`CLAUDE_MEM_HOST_OBSERVER_PORT=${raw} is not a valid port (1-65535)`);
}
} Type guard
const isValidPort = (v: unknown): v is number => typeof v === 'number' && Number.isInteger(v) && v >= 1 && v <= 65535;
Try / catch
try {
const port = resolveHostObserverPort(workerPort, env);
} catch (e) {
if (e instanceof HostObserverUnavailableError && e.message.includes('is not a valid port')) {
delete process.env.CLAUDE_MEM_HOST_OBSERVER_PORT; // fall back to auto-discovery
} else throw e;
} Prevention
- Store only the bare integer port in CLAUDE_MEM_HOST_OBSERVER_PORT — no scheme, slashes, or quotes
- Add a shell-profile check that validates the value with a 1-65535 range test
- Prefer unsetting the variable and letting auto-discovery probe 37777/37778
When it happens
Trigger: Running `npx claude-mem install --provider host` (or any code path calling resolveHostObserverPort / buildHostObserverSettings) with CLAUDE_MEM_HOST_OBSERVER_PORT set to something parsePort rejects — e.g. 'http://127.0.0.1:4141', '4141/', '0', '99999', 'abc', or whitespace.
Common situations: Copy-pasting a full base URL instead of the bare port from an observer's docs; setting the variable in shell rc with quotes/newline; typos like '414l'; setting it to 0 or a 6-digit out-of-range port.
Understand the failure class
Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.
Related errors
- CLAUDE_MEM_HOST_OBSERVER_PORT=${configured} is the claude-me
- 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
- CLAUDE_MEM_REDIS_URL must use redis:// or rediss://
AI-assisted analysis of thedotmack/claude-mem@8bc631a71a (2026-09-09).
Data as JSON: /api/errors/8355edf293275e05.
Report an issue: GitHub.