{"record":{"id":"4d78970b890df409","repo":"rohitg00/agentmemory","slug":"eaddrinuse","errorCode":"EADDRINUSE","errorMessage":"[agentmemory] Viewer port ${requestedPort} is in use while bound to ${host}; not retrying because non-loopback viewer binds require VIEWER_ALLOWED_HOSTS to match the exact port. Free the port, choose another viewer port, or unset AGENTMEMORY_VIEWER_HOST to keep the safe loopback bind.","messagePattern":"\\[agentmemory\\] Viewer port (.+?) is in use while bound to (.+?); not retrying because non-loopback viewer binds require VIEWER_ALLOWED_HOSTS to match the exact port\\. Free the port, choose another viewer port, or unset AGENTMEMORY_VIEWER_HOST to keep the safe loopback bind\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/viewer/server.ts","lineNumber":370,"sourceCode":"    }\n  });\n\n  server.on(\"error\", (err: NodeJS.ErrnoException) => {\n    if (\n      err.code === \"EADDRINUSE\" &&\n      inboundSecret === null &&\n      attempt < MAX_VIEWER_PORT_RETRIES\n    ) {\n      attempt++;\n      currentPort = requestedPort + attempt;\n      setImmediate(tryListen);\n      return;\n    }\n    if (err.code === \"EADDRINUSE\") {\n      boundViewerPort = null;\n      viewerSkipped = true;\n      if (inboundSecret !== null) {\n        console.warn(\n          `[agentmemory] Viewer port ${requestedPort} is in use while bound to ${host}; not retrying because non-loopback viewer binds require VIEWER_ALLOWED_HOSTS to match the exact port. Free the port, choose another viewer port, or unset AGENTMEMORY_VIEWER_HOST to keep the safe loopback bind.`,\n        );\n      } else {\n        console.warn(\n          `[agentmemory] Viewer ports ${requestedPort}-${requestedPort + MAX_VIEWER_PORT_RETRIES} all in use, skipping viewer.`,\n        );\n      }\n    } else {\n      boundViewerPort = null;\n      viewerSkipped = true;\n      console.error(`[agentmemory] Viewer error:`, err.message);\n    }\n  });\n\n  tryListen();\n\n  return server;\n}","sourceCodeStart":352,"sourceCodeEnd":388,"githubUrl":"https://github.com/rohitg00/agentmemory/blob/e04ba88819c365c9acf9d6661ea802143e728bd6/src/viewer/server.ts#L352-L388","documentation":"When the viewer HTTP server fails to bind, startViewerServer inspects the error. For EADDRINUSE on a non-loopback host (an inboundSecret is configured, meaning AGENTMEMORY_VIEWER_HOST is set), it does not retry other ports because non-loopback binds require VIEWER_ALLOWED_HOSTS to include the exact port. It warns with this message and skips the viewer entirely.","triggerScenarios":"startViewerServer (called by viewerServer/viewer/server) gets err.code === 'EADDRINUSE' while host is non-loopback (inboundSecret !== null): the requested viewer port is occupied by another process, and port-hopping is disabled for non-loopback binds.","commonSituations":"Another agentmemory daemon or dev server already listening on the requested port; stale process holding the port; setting AGENTMEMORY_VIEWER_HOST=0.0.0.0 in docker where the port is taken by a sidecar; two daemons started from the same config.","solutions":["Free the requested port (find the process with lsof -i :PORT or ss -ltnp and stop it).","Set a different viewer port via the viewer port configuration so it doesn't collide.","Unset AGENTMEMORY_VIEWER_HOST to return to the safe loopback bind, which can retry the next port.","If binding non-loopback intentionally, ensure VIEWER_ALLOWED_HOSTS matches the exact host:port."],"exampleFix":"// before\nAGENTMEMORY_VIEWER_HOST=0.0.0.0  # port 49135 already in use, no retry\n// after\nunset AGENTMEMORY_VIEWER_HOST  # loopback bind retries next port\n# or\nlsof -ti :49135 | xargs kill","handlingStrategy":"validation","validationCode":"import { createServer } from \"node:net\";\nexport function isPortFree(port: number, host = \"0.0.0.0\"): Promise<boolean> {\n  return new Promise((resolve) => {\n    const s = createServer();\n    s.once(\"error\", () => resolve(false));\n    s.once(\"listening\", () => s.close(() => resolve(true)));\n    s.listen(port, host);\n  });\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check the viewer port is free before starting a non-loopback-bound daemon.","Only set AGENTMEMORY_VIEWER_HOST when you also configure VIEWER_ALLOWED_HOSTS correctly.","Run a single agentmemory daemon per host, or assign distinct viewer ports.","Prefer the default loopback bind unless remote access is required."],"tags":["network","port-in-use","viewer","bind"],"backgroundTag":"address-already-in-use","analyzedSha":"e04ba88819c365c9acf9d6661ea802143e728bd6","analyzedAt":"2026-08-30T01:07:40.754Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}