Node.js lokalny serwer – najczęstsze przyczyny i naprawa

Napraw lokalny serwer Node.js: EADDRINUSE, ERR_CONNECTION_REFUSED, zajęty port 3000, CORS, 404 i firewall Windows.

Objawy i pierwsze rozróżnienie problemu

Node.js lokalny serwer w Windows najczęściej psuje się w 3 miejscach: proces Node.js nie startuje, przeglądarka nie łączy się z adresem localhost albo aplikacja Express działa, ale zwraca 404, CORS lub Cannot GET /. MDN definiuje origin przez 3 elementy: schemat, host i port, dlatego localhost:5173 oraz localhost:3000 są dla przeglądarki różnymi originami (źródło: MDN Web Docs, CORS, 2025).

Co oznacza ERR_CONNECTION_REFUSED?

ERR_CONNECTION_REFUSED localhost to błąd połączenia, który oznacza, że pod wskazanym adresem i portem nie ma procesu nasłuchującego albo połączenie zostało odrzucone przez system. W praktyce widzę to najczęściej po wpisaniu starego adresu, na przykład http://localhost:3000, gdy Vite uruchomił frontend na 5173, a API działa na 3001.

  • Brak procesu Node.js – serwer zakończył pracę po błędzie składni, brakującej zmiennej środowiskowej albo wyjątku w kodzie startowym.
  • Zły port – użytkownik wpisuje 3000, ale terminal pokazuje Local: http://localhost:5173/ albo Server listening on 3001.
  • Zły protokół – aplikacja działa przez HTTP, a przeglądarka próbuje wejść na HTTPS, co daje mylące objawy połączenia.
  • Nasłuch tylko na innym adresie – serwer może słuchać na 127.0.0.1, ale nie na adresie LAN komputera, więc telefon w WiFi go nie zobaczy.
  • Awaria przed listen() – kod dochodzi do importów, ale nie wykonuje server.listen(), więc Node.js startuje i natychmiast kończy proces.

Co oznacza EADDRINUSE w terminalu?

EADDRINUSE Node.js to komunikat systemowy informujący, że wybrany adres i port są już zajęte. W Node.js dotyczy to wywołania server.listen(), czyli momentu, w którym aplikacja próbuje zarezerwować port, na przykład 3000 (źródło: Node.js Net API, 2025).

„When the server has been bound after calling server.listen(), the listening event will be emitted.” – Node.js Documentation, Net API, 2025

Jeżeli poprzedni terminal z projektem nadal działa, drugie uruchomienie npm run dev może zakończyć się błędem port 3000 zajęty. Nie jest to awaria Node.js jako platformy, tylko konflikt zasobu systemowego.

Czy 404 oznacza awarię Node.js?

Nie. Status 404, komunikat Cannot GET / w Express albo pusta odpowiedź z API zwykle oznaczają, że serwer działa, ale nie ma obsługi konkretnej ścieżki, metody HTTP lub prefiksu routera.

  • Cannot GET / – Express nie ma route dla metody GET i ścieżki /.
  • GET /api/users zwraca 404 – router mógł zostać zamontowany pod /api/v1, więc poprawny adres to /api/v1/users.
  • POST działa, GET nie działa – endpoint istnieje tylko dla metody POST, więc test z paska adresu przeglądarki nie wystarczy.
  • Frontend pokazuje pustą stronę – problem może leżeć w bundle frontendu, a nie w API Node.js.

Jak odróżnić problem portu od błędu w kodzie?

Najprostsza reguła diagnostyczna: zmieniaj jedną rzecz naraz i testuj po każdym kroku. Jeżeli terminal pokazuje EADDRINUSE, nie poprawiaj CORS. Jeżeli DevTools pokazuje 404, nie wyłączaj zapory Windows.

Objaw Najbardziej prawdopodobna przyczyna Pierwszy test
ERR_CONNECTION_REFUSED Brak procesu na porcie lub zły adres Sprawdź terminal i port z logu startowego
EADDRINUSE Port zajęty przez poprzedni proces Użyj netstat i sprawdź PID
Cannot GET / Brak route dla GET / w Express Testuj konkretny endpoint, na przykład /api/health
CORS error Frontend i API mają różne originy Sprawdź DevTools > Network i nagłówki CORS

Naprawa konfliktu portu

Konflikt portu w Node.js to sytuacja, w której proces próbuje uruchomić lokalny serwer na porcie zajętym przez inną aplikację, charakteryzująca się błędem EADDRINUSE, numerem portu w logu oraz brakiem nowego procesu nasłuchującego. Najczęściej dotyczy portów 3000, 3001, 5173, 8080 i 5000.

Jak znaleźć proces na porcie 3000?

Na Windows uruchom PowerShell albo cmd i sprawdź, który PID zajmuje port. Dla klasycznego projektu Express wpisz:

  1. Sprawdź port 3000 – wpisz netstat -ano | findstr :3000, aby zobaczyć procesy powiązane z tym portem.
  2. Odczytaj PID – ostatnia kolumna wyniku netstat to numer procesu, na przykład 18432.
  3. Sprawdź nazwę procesu – wpisz tasklist /FI „PID eq 18432”, aby upewnić się, czy to node.exe.
  4. Porównaj z Menedżerem zadań – otwórz Menedżer zadań > Szczegóły i włącz kolumnę PID, jeśli jej nie widzisz.
  5. Nie zamykaj w ciemno – jeżeli PID należy do Docker Desktop, WSL, bazy danych lub innego narzędzia, zmień port aplikacji zamiast ubijać proces.

W mojej praktyce najwięcej błędów pojawia się po zamknięciu okna edytora bez zatrzymania terminala. Proces node.exe zostaje w tle, a kolejne npm run dev próbuje użyć tego samego portu.

Jak usunąć EADDRINUSE bez utraty pracy?

Najpierw wróć do terminala, w którym działa projekt, i naciśnij Ctrl+C. To bezpieczniejsze niż natychmiastowe zabijanie procesu, bo watcher może zapisać stan, zamknąć połączenia i zwolnić port bez uszkadzania plików tymczasowych.

  • Ctrl+C w aktywnym terminalu – bezpiecznie zatrzymuje większość serwerów Express, Vite, Next.js i nodemon.
  • taskkill po PID – użyj tylko wtedy, gdy wiesz, który proces zajmuje port, na przykład taskkill /PID 18432 /F.
  • Zmiana portu na 3001 – dobry wariant ostrożny, gdy nie masz pewności, czy port 3000 należy do innego projektu.
  • Restart terminala – pomaga, gdy skrypt dev zawiesił się, ale nie powinien zastępować sprawdzenia PID.
  • Restart komputera – działa, ale jest najmniej precyzyjny i nie pokazuje pierwotnej przyczyny problemu.

Czy można zabić wszystkie node.exe?

Można, ale to ryzykowne. Zamknięcie wszystkich procesów node.exe może przerwać inne projekty, procesy build, lokalne workery, serwer Vite, watcher TypeScript albo zadanie generowania plików.

Bezpieczniej zamknąć tylko proces wskazany przez netstat findstr port. Jeżeli pracujesz nad kilkoma projektami, zapisz niezapisane pliki w edytorze, sprawdź aktywne terminale i dopiero wtedy użyj taskkill.

Kiedy lepiej zmienić port niż zamykać proces?

Zmień port, gdy proces zajmujący 3000 należy do innej aplikacji albo nie masz pewności, co uruchomiłeś. W Express zwykle wystarczy ustawić zmienną PORT=3001, w Vite parametr –port 5174, a w Next.js next dev -p 3001.

Warto wtedy zaktualizować także adresy w frontendzie, pliku .env i dokumentacji projektu, na przykład w instrukcji Node.js lokalny serwer krok po kroku.

Naprawa adresu, firewalla i dostępu z sieci

Dostęp sieciowy do lokalnego serwera Node.js to konfiguracja adresu nasłuchu, profilu sieci Windows i zapory, charakteryzująca się różnicą między localhost, 127.0.0.1, 0.0.0.0 oraz adresem LAN komputera. To ważne, gdy aplikację testujesz nie tylko na tym samym komputerze, ale też na telefonie, tablecie albo drugim laptopie.

Dlaczego telefon nie widzi localhost?

localhost zawsze oznacza urządzenie, na którym wpisujesz adres. Na komputerze localhost:3000 wskazuje komputer, ale na telefonie ten sam adres wskazuje telefon, a nie laptop z uruchomionym Node.js.

  1. Na komputerze testuj localhost – wpisz http://localhost:3000 oraz http://127.0.0.1:3000, aby sprawdzić dostęp lokalny.
  2. Sprawdź adres IP komputera – użyj ipconfig i znajdź adres IPv4 karty WiFi, na przykład 192.168.1.42.
  3. Na telefonie wpisz adres LAN – użyj http://192.168.1.42:3000, nie localhost.
  4. Ustaw nasłuch na 0.0.0.0 – wiele narzędzi dev wymaga parametru host, aby serwer był widoczny w sieci LAN.
  5. Upewnij się, że urządzenia są w tej samej sieci – telefon w LTE albo w izolowanej sieci gościnnej WiFi nie zobaczy komputera.

Czy firewall Windows blokuje lokalny serwer?

Zapora Windows zwykle nie blokuje połączenia z tego samego komputera przez localhost. Może jednak blokować ruch przychodzący z telefonu lub innego komputera w LAN, szczególnie gdy sieć ma profil Publiczna.

„Windows Defender Firewall helps prevent hackers or malicious software from gaining access to your PC through the Internet or a network.” – Microsoft Support, Windows Security, 2024

Przed dodaniem reguły sprawdź Ustawienia > Sieć i internet > WiFi > właściwości sieci. W domu zwykle wybiera się profil Prywatna, a w kawiarni, hotelu i biurze coworkingowym profil Publiczna.

Jak bezpiecznie testować w sieci WiFi?

Jeżeli lokalne API zawiera tokeny, dane testowe klientów albo panel administracyjny bez logowania, nie wystawiaj go na publiczne WiFi. Dopuszczanie node.exe w zaporze dla sieci publicznej jest wygodne, ale zwiększa ryzyko, że ktoś w tej samej sieci spróbuje wejść na aplikację.

  • Sieć prywatna – używaj jej w domu lub zaufanym biurze, gdy znasz urządzenia podłączone do routera.
  • Sieć publiczna – nie otwieraj portów dev, jeśli aplikacja nie ma uwierzytelniania i rate limitu.
  • Adres 127.0.0.1 – wybierz go, gdy serwer ma być dostępny tylko na tym komputerze.
  • Adres 0.0.0.0 – używaj go świadomie, gdy potrzebujesz testów z telefonu lub telewizora w LAN.
  • VPN i sieci firmowe – mogą zmieniać routing, DNS i reguły zapory, więc testuj także po odłączeniu VPN.

Jak sprawdzić port bez przeglądarki?

Na Windows przydaje się Test-NetConnection. Komenda Test-NetConnection 127.0.0.1 -Port 3000 pokaże, czy port odpowiada lokalnie, a Test-NetConnection 192.168.1.42 -Port 3000 pomoże sprawdzić dostęp przez sieć LAN.

Jeżeli lokalnie test przechodzi, a telefon nadal nie łączy się z aplikacją, problemem jest najczęściej host, profil sieci, izolacja klientów WiFi albo reguła zapory. Więcej takich procedur pasuje do instrukcji Windows jak sprawdzić zajęty port.

Naprawa błędów aplikacji: 404, CORS, złe ścieżki

Błąd aplikacji w lokalnym API Node.js to sytuacja, w której serwer odpowiada, ale odpowiedź nie pasuje do oczekiwań klienta, charakteryzująca się statusem 404, błędem CORS localhost, złą metodą HTTP lub niepoprawnym adresem endpointu. To inna klasa problemu niż EADDRINUSE i ERR_CONNECTION_REFUSED.

Dlaczego API zwraca 404?

W Express komunikat Cannot GET / oznacza zwykle brak trasy dla GET /. Serwer działa, ale nie wie, co ma zrobić z żądaniem pod tym adresem.

  • Brak root route – aplikacja ma tylko /api/health, więc wejście na / zwraca 404.
  • Zły prefiks API – frontend woła /users, a Express ma router pod /api/users.
  • Zła metoda HTTP – endpoint POST /api/login nie odpowie poprawnie na zwykłe wejście z paska adresu.
  • Zły port frontendu – żądanie idzie do Vite na 5173, a nie do API na 3000.
  • Literówka w ścieżce/api/project i /api/projects to dwa różne adresy.

Jak rozpoznać problem CORS?

CORS pojawia się po stronie przeglądarki, gdy frontend i API mają różne originy. Dla przeglądarki http://localhost:5173 i http://localhost:3000 to dwa różne originy, ponieważ różni się port (źródło: MDN Web Docs, CORS, 2025).

„Cross-Origin Resource Sharing is an HTTP-header based mechanism that allows a server to indicate any origins other than its own.” – MDN Web Docs, CORS, 2025

Typowy objaw to czerwony błąd w DevTools > Console i zablokowane żądanie w DevTools > Network. Rozwiązaniem jest jawne dopuszczenie originu frontendu w API albo skonfigurowanie proxy w Vite.

Jak sprawdzić endpoint poza przeglądarką?

Test poza przeglądarką pozwala odróżnić problem CORS od problemu serwera. CORS egzekwuje przeglądarka, więc curl albo Invoke-WebRequest może dostać poprawną odpowiedź, mimo że frontend jest blokowany.

  1. Sprawdź endpoint zdrowia – użyj curl http://localhost:3000/api/health albo Invoke-WebRequest http://localhost:3000/api/health.
  2. Sprawdź dokładny URL z DevTools – skopiuj adres z zakładki Network, zamiast przepisywać go ręcznie.
  3. Sprawdź metodę HTTP – dla POST użyj narzędzia typu Postman, Insomnia albo curl z parametrem metody.
  4. Sprawdź status odpowiedzi200 oznacza sukces, 404 złą ścieżkę, 500 błąd aplikacji, a 0 w przeglądarce często wskazuje blokadę CORS.
  5. Sprawdź nagłówki CORS – odpowiedź API powinna zawierać właściwy Access-Control-Allow-Origin dla środowiska dev.

Kiedy użyć Vite API proxy?

Vite API proxy jest wygodne, gdy frontend działa na 5173, a API na 3000. Frontend wysyła wtedy żądanie do własnego originu, na przykład /api/users, a dev server przekazuje je do Node.js.

To ogranicza liczbę wyjątków CORS w kodzie backendu i pozwala utrzymać podobny adres API w komponentach. Szczegółową procedurę warto połączyć z instrukcją jak naprawić CORS w lokalnym API.

Jak bezpiecznie zrestartować lokalny serwer?

Bezpieczny restart lokalnego serwera Node.js to kontrolowana procedura zatrzymania procesu, sprawdzenia portu, ponownego uruchomienia i testu endpointów, charakteryzująca się brakiem przypadkowego zamykania innych projektów, jasnym logiem startowym oraz testem kontrolnym. Taki restart jest szybszy niż zgadywanie i zmniejsza ryzyko utraty pracy.

Jak czytać logi npm run dev?

Logi po npm run dev mówią, czy aplikacja wystartowała, na jakim porcie działa i jaki błąd zatrzymał proces. Nie pomijaj pierwszych 20-30 linii, bo tam zwykle jest brakujący import, zmienna środowiskowa albo stack trace.

  • Local URL – informuje o właściwym adresie frontendu lub serwera dev, na przykład http://localhost:5173/.
  • Server listening – informuje, że backend wykonał listen() i powinien przyjmować połączenia.
  • EADDRINUSE – wskazuje konflikt portu i wymaga sprawdzenia PID, a nie poprawiania route.
  • Module not found – oznacza problem zależności albo ścieżki importu, często po zmianie branchy.
  • Unhandled exception – pokazuje błąd aplikacji, który mógł zakończyć proces przed uruchomieniem serwera.

Jaka jest procedura restartu krok po kroku?

Stosuję prostą procedurę, bo eliminuje większość pomyłek przy lokalnych projektach Express, Vite i React. Nie trzeba od razu czyścić cache, usuwać node_modules ani restartować Windows.

  1. Zapisz zmiany w edytorze – niezapisany plik konfiguracyjny może sprawić, że restart odtworzy stary błąd.
  2. Zatrzymaj serwer przez Ctrl+C – zamknij proces z terminala projektu, nie przez losowe ubijanie node.exe.
  3. Sprawdź port – użyj netstat -ano | findstr :3000, jeśli wcześniej był błąd EADDRINUSE.
  4. Uruchom projekt ponownie – wpisz npm run dev i przeczytaj adres wypisany w terminalu.
  5. Przetestuj root i endpoint – sprawdź /, /api/health i konkretną ścieżkę używaną przez frontend.
  6. Sprawdź DevTools > Network – potwierdź metodę HTTP, status, pełny URL i odpowiedź serwera.

Kiedy czyścić node_modules albo cache?

Czyszczenie node_modules to rozwiązanie późniejsze, nie pierwszy krok. Ma sens po zmianie wersji Node.js, uszkodzonym lockfile, konflikcie zależności albo błędach typu Cannot find module, ale nie naprawi zajętego portu.

  • Po zmianie branchy – uruchom npm install, jeśli package-lock.json zmienił zależności.
  • Po zmianie wersji Node.js – sprawdź node -v i wersję wymaganą przez projekt.
  • Po błędach binarek – usuń node_modules dopiero po upewnieniu się, że problem dotyczy zależności.
  • Przy błędzie portu – nie czyść zależności, tylko sprawdź proces i PID.

Jak dokumentować naprawę dla kolejnych uruchomień?

Po naprawie dopisz do README rzeczywisty port, komendę startową i endpoint kontrolny. Jedna linia typu API: http://localhost:3000/api/health oszczędza czas przy następnym uruchomieniu projektu.

Jeżeli projekt ma kilka usług, opisz je osobno: frontend Vite na 5173, backend Express na 3000, baza danych na 5432 albo 3306. Dla początkujących dobrym uzupełnieniem jest temat co oznacza lokalny serwer Node.js.

Najczęściej zadawane pytania

Co oznacza EADDRINUSE w Node.js?

EADDRINUSE oznacza, że wybrany port jest już zajęty przez inny proces. Najczęściej działa poprzednia instancja serwera, drugi projekt Node.js albo narzędzie dev używające tego samego portu. Sprawdź PID przez netstat -ano | findstr :3000 i zamknij tylko właściwy proces.

Dlaczego localhost:3000 nie działa mimo uruchomienia npm run dev?

Aplikacja może działać na innym porcie, na przykład 3001 lub 5173, albo proces zakończył się po błędzie startowym. Zawsze czytaj adres wypisany w terminalu po npm run dev. Jeżeli widzisz ERR_CONNECTION_REFUSED, sprawdź, czy proces nadal działa.

Czy mogę zamknąć wszystkie procesy node.exe?

To ryzykowne, jeśli masz uruchomionych kilka projektów, watcherów, workerów albo buildów. Lepiej ustalić PID procesu zajmującego konkretny port i zamknąć tylko ten proces. Masowe zamknięcie node.exe może przerwać inne zadania i utrudnić diagnozę.

Dlaczego mam błąd CORS między localhost:5173 i localhost:3000?

Dla przeglądarki różne porty oznaczają różne originy, więc frontend na 5173 i API na 3000 są traktowane osobno. Backend musi dopuścić origin frontendu nagłówkami CORS albo frontend powinien korzystać z proxy dev servera. Samo działanie endpointu w curl nie oznacza, że przeglądarka przepuści żądanie.

Czy firewall Windows wpływa na localhost?

Zwykle nie blokuje połączeń z tego samego komputera na localhost albo 127.0.0.1. Może jednak zablokować dostęp z telefonu, tabletu lub drugiego komputera w sieci LAN. Sprawdź profil sieci Windows i nie dopuszczaj ruchu w sieci publicznej, jeśli aplikacja ma dane testowe lub tokeny.

Jak sprawdzić, czy port 3000 jest zajęty?

Na Windows użyj netstat -ano | findstr :3000, a potem sprawdź PID komendą tasklist /FI „PID eq numer”. W Menedżerze zadań możesz wejść w zakładkę Szczegóły i porównać numer PID. To bezpieczniejsze niż zgadywanie, który terminal trzeba zamknąć.

Co oznacza Cannot GET / w Express?

Cannot GET / oznacza, że serwer Express działa, ale nie ma trasy obsługującej metodę GET dla ścieżki /. To nie musi być błąd, jeśli API ma działać tylko pod /api. Przetestuj właściwy endpoint, na przykład /api/health lub /api/users.

Kiedy używać 0.0.0.0 zamiast localhost?

Adres 0.0.0.0 stosuj wtedy, gdy lokalny serwer ma być dostępny z telefonu albo innego urządzenia w tej samej sieci LAN. Do pracy tylko na komputerze bezpieczniejszy jest localhost lub 127.0.0.1. Nie wystawiaj aplikacji dev na publiczne WiFi, jeśli nie ma zabezpieczeń.

Źródła i literatura

  1. Node.js Documentation, Net API – server.listen, dokumentacja oficjalna Node.js, 2025.
  2. Node.js Documentation, HTTP API, dokumentacja oficjalna Node.js, 2025.
  3. MDN Web Docs, Cross-Origin Resource Sharing (CORS), Mozilla, 2025.
  4. Microsoft Support, Windows Defender Firewall and network protection, dokumentacja pomocy Microsoft, 2024.
  5. Microsoft Learn, Test-NetConnection, dokumentacja PowerShell, 2024.