{"record":{"id":"0ea0159e089e40bc","repo":"thedotmack/claude-mem","slug":"claude-mem-host-observer-port-configured-is-occ","errorCode":null,"errorMessage":"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.","messagePattern":"CLAUDE_MEM_HOST_OBSERVER_PORT=(.+?) 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\\.","errorType":"exception","errorClass":"HostObserverUnavailableError","httpStatus":null,"severity":"error","filePath":"src/npx-cli/cmem-memory-credentials.ts","lineNumber":249,"sourceCode":"): string {\n  const worker = parsePort(typeof workerPort === 'number' ? workerPort : nonEmptyString(workerPort));\n  const configuredRaw = nonEmptyString(env.CLAUDE_MEM_HOST_OBSERVER_PORT);\n  if (configuredRaw) {\n    const configured = parsePort(configuredRaw);\n    if (configured == null) {\n      throw new HostObserverUnavailableError(\n        `CLAUDE_MEM_HOST_OBSERVER_PORT=${configuredRaw} is not a valid port. Set it to the port your OpenAI-compatible observer already listens on.`,\n      );\n    }\n    if (worker != null && configured === worker) {\n      throw new HostObserverUnavailableError(\n        `CLAUDE_MEM_HOST_OBSERVER_PORT=${configured} is the claude-mem worker port. Point it at your OpenAI-compatible observer instead.`,\n      );\n    }\n    const status = probe(configured);\n    if (status === 'observer') return String(configured);\n    if (status === 'occupied') {\n      throw new HostObserverUnavailableError(\n        `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.`,\n      );\n    }\n    throw new HostObserverUnavailableError(\n      `CLAUDE_MEM_HOST_OBSERVER_PORT=${configured} has nothing listening. Start your OpenAI-compatible observer on that port, then rerun with --provider host.`,\n    );\n  }\n\n  const candidates = hostObserverCandidatePorts(workerPort, env);\n  for (const port of candidates) {\n    const status = probe(port);\n    if (status === 'observer') return String(port);\n  }\n\n  throw new HostObserverUnavailableError(\n    `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.`,\n  );\n}","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/8bc631a71a487424b866756e43a6efa4574cc66b/src/npx-cli/cmem-memory-credentials.ts#L231-L267","documentation":"When CLAUDE_MEM_HOST_OBSERVER_PORT is set, the port must host an OpenAI-compatible endpoint (the probe hits /v1/models and /v1/chat/completions and checks the response shape). If something answers but is not an observer — or the port refuses a bind test during the sync probe — claude-mem refuses to use it rather than misidentifying the service.","triggerScenarios":"resolveHostObserverPort probes the configured port; probeHostObserverPortSync returns 'occupied' because another process (a dev server, another app, a stale worker) is listening there and its responses do not look OpenAI-compatible.","commonSituations":"Port reused by a unrelated local web app; leftover process from a previous session squatting on the port; pointing at a UI port of a tool whose API is on a different port.","solutions":["Stop the process occupying that port (lsof -i :PORT, then kill it), and rerun the install","Find your observer's real API port and set CLAUDE_MEM_HOST_OBSERVER_PORT to it, e.g. export CLAUDE_MEM_HOST_OBSERVER_PORT=4141","Verify the endpoint responds like OpenAI: curl -H 'Authorization: Bearer x' http://127.0.0.1:$CLAUDE_MEM_HOST_OBSERVER_PORT/v1/models should return a model list","Unset CLAUDE_MEM_HOST_OBSERVER_PORT to let auto-discovery probe 37777/37778 instead"],"exampleFix":"// before\nexport CLAUDE_MEM_HOST_OBSERVER_PORT=3000  # occupied by a dev server\n// after\nlsof -ti :3000 | xargs kill\nexport CLAUDE_MEM_HOST_OBSERVER_PORT=4141  # actual observer port","handlingStrategy":"validation","validationCode":"const res = await fetch(`http://127.0.0.1:${port}/v1/models`, { headers: { Authorization: 'Bearer x' } }).catch(() => null);\nconst body = res?.ok ? await res.text() : '';\nif (!body.includes('data')) throw new Error(`Port ${port} is not an OpenAI-compatible observer`);","typeGuard":null,"tryCatchPattern":"try {\n  const port = resolveHostObserverPort(workerPort, env);\n} catch (e) {\n  if (e instanceof HostObserverUnavailableError && e.message.includes('is occupied by a process')) {\n    // inspect/kill the squatter or reconfigure the port, then retry\n  } else throw e;\n}","preventionTips":["Before installing, curl /v1/models on the configured port and confirm an OpenAI-style response","Use lsof -i :PORT to confirm which process owns the port before pointing claude-mem at it","Reserve dedicated ports for the observer so unrelated dev servers do not collide"],"tags":["port-conflict","network","host-observer","env-var"],"backgroundTag":"address-already-in-use","analyzedSha":"8bc631a71a487424b866756e43a6efa4574cc66b","analyzedAt":"2026-09-09T10:47:06.009Z","contentChangedAt":"2026-09-09T10:47:06.009Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}