#Что означает ошибка и когда она возникает
Ошибка listen EADDRINUSE: address already in use означает, что адрес и порт уже заняты слушающей программой. При попытке запустить второй экземпляр того же Node.js-сервера это обычно нормально: первый процесс уже принимает подключения. Решение — найти владельца порта и понять, нужен ли вообще второй сервер, а не завершать неизвестные процессы.
#Как отличить возможные причины
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Первый экземпляр приложения работаетВ другом терминале, службе или контейнере уже запущен тот же сервер. | Программа отвечает на localhost:3000 и процесс владеет слушающим сокетом. | Переиспользовать первый экземпляр или корректно остановить его. |
| Порт занят другой программойОдна из сторонних служб уже слушает тот же адрес/порт. | По PID видно другое имя процесса; Node.js не запускается с этим портом. | Выбрать другой свободный порт или согласовать освобождение с владельцем. |
| Процесс повторно вызывает listenВнутри одного приложения server.listen() вызван более одного раза без закрытия сервера. | Сообщение ERR_SERVER_ALREADY_LISTEN либо похожая ошибка после повторной инициализации. | Устранить двойной вызов, сделать запуск идемпотентным. |
#Пошаговая диагностика и устранение
- Запишите адрес, порт и способ запускаОткройте журнал второго экземпляра Node.js. Найдите
EADDRINUSE, например127.0.0.1:3000, либо адрес::с портом. Узнайте, как вы его запускаете: в двух терминалах, через npm start, диспетчер процессов или Docker. Не закрывайте все процессы Node.js: на машине могут работать другие сервисы. - Убедитесь, что первый сервер действительно работаетВ браузере откройте адрес своего локального приложения, например http://127.0.0.1:3000, только если именно этот порт указан в вашем проекте. Если сервер отвечает, ошибка второго процесса может означать обычную попытку повторного запуска. Если соединения нет, всё равно проверьте процесс-владельца: программа может слушать другой адрес или не быть HTTP.
- Найдите слушающий процесс в WindowsЗапустите PowerShell через меню «Пуск», обычных прав достаточно для первой проверки. Выполните
Get-NetTCPConnection -LocalPort 3000 -State Listen | Select-Object LocalAddress,LocalPort,OwningProcess, заменив 3000 фактическим портом. По OwningProcess найдите процесс в диспетчере задач (Ctrl+Shift+Esc → «Подробности» → столбец «ИД процесса») илиGet-Process -Id <PID>с подстановкой реального числа. Если сведений нет или доступ запрещён, обратитесь к администратору. - Найдите слушающий процесс в Linux или macOSВ Linux откройте терминал и выполните
ss -ltnp, затем найдите строку с нужным локальным портом и состоянием LISTEN. В macOS используйтеlsof -nP -iTCP:3000 -sTCP:LISTEN, заменив порт. Если имя процесса скрыто из-за разрешений, не запускайте команду принудительного завершения; проверьте владельца в журнале службы или попросите администратора. - Решите, нужно ли завершать первый экземплярЕсли первый процесс открыт в вашем терминале, перейдите в него и нажмите Ctrl+C. Дождитесь сообщения об остановке и проверьте, что слушающий порт освободился. Если первый запущен через systemd, PM2, IDE или Docker, используйте штатное управление именно этой службой после согласования, а не taskkill/kill по неустановленному PID.
- Для параллельного теста задайте другой портКогда два экземпляра действительно нужны, выберите другой свободный порт, например 3100, и настройте его способом, предусмотренным приложением. В учебном примере ниже второй аргумент команды node задаёт порт; первая копия слушает 3000, вторая — 3100. Для реального приложения проверьте поддержку аргумента PORT и возможные конфликты с прокси.
- Разберите повторный listen внутри одного процессаНайдите все
.listen(в исходном коде. Если сервер создаётся или запускается в обработчике запроса, перенесите один вызов listen в процедуру запуска. В одном экземпляре проверяйтеserver.listeningи не вызывайте listen вторично без завершившегося server.close; это исправляет другой код ошибки — ERR_SERVER_ALREADY_LISTEN. - Проверьте оба экземпляра и способ откатаВ одной тестовой папке создайте server.cjs из примера. Первый терминал:
node server.cjs 3000— сервер работает; второй терминал: та же команда — печать EADDRINUSE; после остановки второго можно выполнитьnode server.cjs 3100и увидеть второй успешный запуск. Остановите оба Ctrl+C. Если меняли порт в конфигурации продукта, верните прежнее значение и перезапустите только свою службу. - Команды для отдельных ситуацийВыберите только подходящий вариант. Это не одна последовательность: часть команд диагностирует проблему, а часть меняет настройки или данные.
#Минимальный пример и проверка на тестовом проекте
const http = require("node:http");
const port = Number(process.argv[2] ?? 3000);
const server = http.createServer((req, res) => res.end("OK"));
server.on("error", err => {
console.error("Ошибка запуска:", err.code);
process.exitCode = 1;
});
server.listen(port, "127.0.0.1", () => console.log("Слушаю", port));#Проверка результата и действия при неуспехе
Один процесс стабильно слушает согласованный адрес/порт и обслуживает запросы; второй либо не запускается предсказуемо, либо использует другой согласованный порт. Если EADDRINUSE остаётся после остановки своего экземпляра, снова посмотрите владельца порта и журнал управления процессами, не отключайте чужую службу.