gdamian.pl
← Wszystkie wpisy
10 min

9 błędów w n8n, które kosztują najwięcej (i jak je obejść) 

Damian GębalaAutor

Najdroższe błędy w n8n to nie te, które wyrzucają czerwony komunikat na ekranie, tylko te, o których nikt nie wie. Automatyzacja pada po cichu, baza rośnie tydzień za tygodniem, klucz API ląduje w logu, a Ty dowiadujesz się o tym od klienta. Poniżej dziewięć błędów, które widzę najczęściej w realnych wdrożeniach, i sposób obejścia każdego z nich.

Jedno zastrzeżenie na start, bo lubię mówić wprost. Dokumentacja n8n nie publikuje ani jednej kwoty: nie ma tabel cen chmury, kosztów workerów ani wyliczeń, ile zaoszczędzisz po włączeniu trybu kolejki. Nie będę więc obiecywał Ci oszczędności w złotych, bo takiej liczby po prostu nie ma. „Koszt” w tym artykule oznacza Twój czas, godziny przy debugowaniu i przestoje procesu, który mimo błędu wygląda na działający. To najuczciwsza miara, jaką da się tu podać.

Jeśli dopiero zaczynasz i szukasz pierwszego działającego przepływu, zacznij od prostej automatyzacji w n8n krok po kroku. W tekście niżej zakładam, że masz już pierwszy działający workflow i znasz podstawy tej platformy.

1. Brak obsługi błędów, czyli awaria bez alarmu

To błąd numer jeden i najczęstszy zarazem. Workflow wywala się, nikt nie dostaje wiadomości, Ty patrzysz w panel i widzisz ostatnie udane wykonanie. Problemy rozpoznajesz po pytaniu klienta: „dostałem tylko część maila, reszta nie przyszła”.

Obejście jest banalne, a mimo to rzadko ktoś je robi. Tworzysz osobny workflow, wstawiasz na początku węzeł Error Trigger i nazywasz go na przykład Error Handler. W każdym chronionym workflowie otwierasz ustawienia i wskazujesz ten handler. Od tej chwili każde nieudane wykonanie odpala Twój własny przepływ, a w nim możesz wysłać alert na Slack, maila albo wpis do bazy, z której czytasz powiadomienia.

Jeden handler możesz podpiąć pod kilkanaście workflowów naraz, więc robotę robisz raz. Do testów służy węzeł Stop And Error, który celowo wywala przebieg i sprawdza, czy alert faktycznie dotarł. Warto też ustawić ponawianie na poziomie węzła: w ustawieniach każdego węzła jest przełącznik automatycznych prób, w którym sam definiujesz liczbę powtórzeń i odczekanie między nimi. Dla bardziej rozbudowanych strategii n8n ma zapętlony węzeł IF z własnym limitem prób.

2. Jeden wielki workflow zamiast pod-workflowów

Drugi błąd to wszystko na jednej kanwie. Sto węzłów, piętnaście gałęzi, jeden ekran, na którym nie da się nic znaleźć. Taki przepływ jest niemal niemożliwy do debugowania, a przy dużej ilości danych kończy się błędem pamięci.

Rozwiązanie nazywa się sub-workflow, czyli wywoływanie jednego przepływu z drugiego. Tworzysz nowy workflow, wstawiasz węzeł Execute Sub-workflow Trigger, przenosisz tam kawałek logiki i wołasz go z głównego przepływu węzłem Execute Workflow. Masz dwa praktyczne powody, żeby to robić: po pierwsze, każdy fragment testujesz osobno, po drugie, wykonania pod-workflowów nie wliczają się do limitu wykonań w Twoim planie.

Nie musisz przepisywać istniejącego przepływu od zera. Zaznaczasz węzły, klikasz prawym przyciskiem na pustej części kanwy i wybierasz Convert to sub-workflow. Ta funkcja działa od n8n 1.97.0, a selekcja musi być ciągła i nie może obejmować węzłów startowych.

Ten sam problem widać przy dużych raportach: jeśli jeden przebieg ciągnie tysiące wierszy, procesowi zwykle brakuje pamięci. Rozwiązanie opisałem osobno przy automatycznym przetwarzaniu raportów.

3. Brak limitu współbieżności, czyli instancja się dusi

Domyślnie n8n nie ogranicza liczby produkcyjnych wykonań działających w tej samej chwili. Przy kilku równoległych webhookach zdarza się, że pętla zdarzeń w Node.js zaczyna się dusić. Panel przestaje odpowiadać, a wykonania piętrzą się w kolejce bez kolejki.

Najprostsze rozwiązanie, dostępne także w wersji darmowej, to włączenie limitu współbieżności jedną zmienną środowiskową: N8N_CONCURRENCY_PRODUCTION_LIMIT. Ustawiasz na przykład 20 i od tej pory wykonania powyżej limitu czekają w kolejce FIFO zamiast wywraczać instancję. Domyślnie limit wyłącza się właśnie dlatego, że większość instalacji nigdy go nie zmienia.

Powyżej progu kilkuset wykonań dziennie potrzebujesz trybu kolejki: EXECUTIONS_MODE=queue, broker Redis i osobne procesy workerów. Worker uruchamiasz z flagą --concurrency, która domyślnie wynosi 10. n8n zaleca ustawienie 5 albo więcej, bo zbyt niska wartość przy dużej liczbie workerów wyczerpie pulę połączeń z bazą. Klucz szyfrowania N8N_ENCRYPTION_KEY musi być identyczny na instancji głównej, workerach i procesach webhooków, inaczej nie odczytają credentiali z bazy.

4. Dane zostają w bazie, pliki w pamięci RAM

Czwarta grupa błędów uderza po kilku miesiącach, gdy wszystko działa. Baza rośnie, dysk się zapełnia, instancja przestaje wstawać po restarcie serwera.

Dokumentacja n8n mówo wprost: przy dużym wolumenie baza może rozrosnąć się do rozmiaru, na który nie ma już miejsca. Domyślne ustawienia są zaskakująco zachowawcze, jeśli nie świadomie ich nie zmienisz. Retencja wynosi 336 godzin, czyli 14 dni, a limit liczby wykonań to 10 000 i przy jego przekroczeniu n8n kasuje dane od najstarszych.

Trzy zmienne robią tu największą różnicę. EXECUTIONS_DATA_MAX_AGE skraca retencję, przykładowo do 168 godzin, czyli tygodnia. EXECUTIONS_DATA_SAVE_ON_SUCCESS=none przestaje zapisywać udane przebiegi, a EXECUTIONS_DATA_SAVE_ON_ERROR=all zostawia te, które się wyważyły. Przy SQLite dodatkowo włącz DB_SQLITE_VACUUM_ON_STARTUP, żeby zwolnić miejsce po usunięciu.

Drugie pół tego samego błędu dotyczy plików. n8n trzyma dane binarne w pamięci procesu, a dokumentacja ostrzega, że to może skutkować awarią przy dużych plikach. Tryb zmienisz zmienną N8N_DEFAULT_BINARY_MODE na filesystem, bazę albo magazyn obiektowy. W bazie pojedyncza kolumna mieści do 1 GB, więc przy większych plikach zostaje tylko magazyn zewnętrzny. Warto wtedy od razu znać granice, o której mowa przy hostowaniu u siebie.

Osobno o pamięci RAM. n8n nie limituje ilości danych, którą każdy węzeł może pobrać, więc procesy bez Twojej wiedzy ciągną za dużo. n8n podaje konkretny przykład podziału: zamiast pobierać 10 000 wierszy na wykonanie, przetwarzaj po 200. Ostrzega też, że węzeł Code zużywa najwięcej pamięci, podobnie ręczne uruchamianie przebiegów, bo n8n robi wtedy kopię danych dla frontendu. Zanim sięgniesz po --max-old-space-size w NODE_OPTIONS, spróbuj po prostu mniej danych na raz.

5. Brak wersji i kopii przepływu

Błąd bezobjawowy, dopóki nie trzeba cofnąć zmiany. Poprawiłeś węzeł, kliknąłeś zapis i workflow przestał działać. Nie masz historii, nie masz kopii, nie masz jak wrócić do wersji sprzed godziny.

n8n ma wbudowane source control, czyli integrację z Gitem. Włączasz ją w Settings, wskazujesz repozytorium i gałąź, a od tej pory każda zmiana jest wersjonowana. Jest jednak haczyk, o którym trzeba powiedzieć wprost: ta funkcja jest dostępna w planach Business i Enterprise, a włączyć ją może wyłącznie właściciel instancji albo jej administrator. Administrator projektu może wypychać zmiany do repozytorium, ale nie może ich z niego pobrać.

Dla produkcji przydaje się jeszcze opcja Protected instance, która blokuje edycję bezpośrednio w panelu i wymusza drogę przez gałąź. Wtedy testujesz na gałęzi, a na produkcję wchodzi dopiero to, co przeszło.

6. Sekrety w kodzie, sekrety w logach

Domyślnie jest nieźle, bo n8n trzyma wszystkie credentiale zaszyfrowane w bazie i domyślnie ogranicza do nich dostęp. Problem zaczyna się w dwóch miejscach, których ludzie nie kontrolują.

Pierwsze to logowanie diagnostyczne. Typowy scenariusz: coś nie działa, dodajesz logowanie na poziomie debug, loguje całe nagłówki żądania razem z nagłówkiem autoryzacji i zapisuje je we wspólnym serwisie. Każdy, kto ma dostęp do logów, widzi wtedy Twoje tokeny. Blog n8n opisuje dokładnie ten scenariusz jako przykład złego zarządzania sekretami.

Drugie to brak zewnętrznego magazynu sekretów. n8n potrafi pobrać klucz z 1Password Connect Server, AWS Secrets Manager, Azure Key Vault, GCP Secrets Manager, HashiCorp Vault lub Infisical, a w polu credential używasz wtedy wyrażenia {{ $secrets.nazwa-sekretu.klucz }}. Istotne ograniczenie: sekrety z zewnętrznego magazynu działają wyłącznie w polach credential, w żadnym innym polu obsługującym wyrażenia. Ta funkcja jest zarezerwowana dla planów płatnych.

Osobno o danych w historii wykonań. Redakcja danych wejścia i wyjścia pojedynczych workflowów działa od n8n 2.16.0, a wymuszenie jej na poziomie całej instancji od 2.26.0. Domyślnie redakcja jest wyłączona, więc historia wykonania pokazuje pełne odpowiedzi API, w tym dane osobowe klientów.

7. Wartości wpisane na sztywno zamiast konfiguracji

Siódmy błąd jest zwykle niewidoczny przy pierwszym wdrożeniu, a bardzo bolesny przy drugim. Adres API, identyfikator kanału, limit, token i nazwa środowiska wpisane prosto w węzły. Zmiana adresu serwera testowego na produkcyjny oznacza otwieranie kilkudziesięciu węzłów po kolei.

Rozwiązanie jest takie, jak wygląda konfiguracja każdego innego narzędzia na serwerze: przenieś wartości do zmiennych środowiskowych. n8n przyjmuje je z pliku konfiguracyjnego albo ze środowiska, a dla wybranych zmiennych dopisując sufiks _FILE wskazujesz osobny plik z wartością, co przy kontenerach bywa wygodniejsze niż sekrety w warstwie obrazu. Dzięki temu ten sam obraz n8n działa na środowisku testowym i produkcyjnym bez żadnej edycji kanwy.

8. Brak logów i brak health checku

Domyślny poziom logowania n8n to info, a wyjście trafia do konsoli. W praktyce oznacza to, że po awarii zostajesz z jednym zdaniem w panelu i własną pamięcią. Sam przestawiłem tak kilka instalacji, gdzie to był pierwszy postęp, jaki zrobiłem.

Ustawienia są proste: N8N_LOG_LEVEL przyjmuje wartości silent, error, warn, info i debug, a N8N_LOG_OUTPUT decyduje, czy logi idą do konsoli, do pliku, czy do obu. Domyślnie jeden plik logu ma 16 MB i n8n trzyma 100 takich plików. Ustawienia N8N_LOG_FILE_SIZE_MAX i N8N_LOG_FILE_COUNT_MAX warto zmienić świadomie, bo przy workerach liczba plików musi być ustawiona inaczej niż na jednej instancji.

W trybie kolejki dochodzi warstwa health checków. Zmienna QUEUE_HEALTH_CHECK_ACTIVE włącza na workerach endpointy /healthz i /healthz/readiness. Wpięcie ich w swój monitoring daje sygnał, że worker padł, zanim zauważysz to po braku raportu. Warto też patrzeć w logi na wpisy o dodawaniu wykonań do kolejki i zwalnianiu z niej, bo to widać, kiedy system zaczyna się zatłapiać.

9. Agent AI bez limitu prób

Jeśli budujesz w n8n agenta z modelem językowym, dziewiąty błąd jest szczególny, bo objawia się jako pożeranie tokenów, a nie jako awaria. Model dostaje błąd z zewnętrznego API, próbuje jeszcze raz, znów nie wychodzi, wchodzi w pętlę i wykonanie trwa.

Blog n8n dzieli awarie na cztery kategorie: transport, błąd usługi zewnętrznej, walidacja wejścia i błąd logiki lub nieoczekiwany format odpowiedzi. Każda wraca do innej warstwy naprawy. Błędy przejściowe, czyli limity żądań i wewnętrzne awarie serwera, powinien obsługiwać mechanizm ponowień w samym węźle, najlepiej z rosnącym odstępem i odczytem nagłówka Retry-After. Warstwa orkiestracji powinna pilnować twardego licznika prób: po przekroczeniu progu, zwykle trzech, pętla się ucina i leci alarm, zamiast krążyć dalej.

Dwie praktyki z tego samego źródła są warte wdrożenia od razu. Po pierwsze, błąd z aplikacji zwracamy modelowi jako czysty, uporządkowany komunikat powiązany z identyfikatorem wywołania narzędzia, zamiast przerywać cały przebieg. Po drugie, stan dostępności usługi trzymamy w Data Table i sprawdzamy dostępność przed każdym wywołaniem API. Jeśli sam budujesz takiego agenta, opisuję to krok po kroku przy połączeniu ChatGPT z n8n.

Dwa drobiazgi, które ciągną za sobą więcej, niż się wydaje

Pierwszy: przetwarzasz tylko pierwszą stronę danych i nawet nie zauważasz. Węzeł HTTP Request ma w opcjach zakładkę Pagination, a ustawienie Update a Parameter in Each Request z wyrażeniem {{ $pageCount + 1 }} wybiera stronę po stronie. Licznik $pageCount startuje od zera, podczas gdy większość API liczy strony od jedynki, więc warto to sprawdzić na pierwszym przebiegu.

Drugi: kod w węźle Code wykonuje się w task runnerze z szerszymi uprawnieniami, niż potrzebuje. Dokumentacja podaje zestaw utwardzeń: obraz distroless z sufiksem w tagu Dockera, użytkownik nobody o identyfikatorach 65532, system plików tylko do odczytu i osobny wolumen na /tmp. Jest jeszcze reguła AppArmor blokująca odczyt plików /proc z zmiennymi środowiska, w których mogą siedzieć sekrety.

Od czego zacząć przy wdrożeniu

Jeśli stawiasz n8n u siebie teraz, kolejność prac jest prostsza niż lista dziewięciu poprawek. Najpierw podepnij handler błędów i alert, bo bez niego każda kolejna zmiana jest ryzykiem. Potem ustaw retencję danych wykonania, bo to jedna zmienna środowiskowa, a baza przestaje rosnąć w nieskończoność. Dopiero potem włącz logowanie do pliku i limity współbieżności, a przy realnym wolumenie przenieś pliki poza pamięć procesu. Dopracowywanie architektury przychodzi na końcu, kiedy masz już działający przepływ i czytelne logi tego, co się dzieje.

Jeżeli zastanawiasz się, czy n8n w ogóle pasuje do Twojej sytuacji, porównanie platform opisuję w tekście o n8n kontra Make i Zapier.

Wszystko powyżej opiera się na oficjalnej dokumentacji n8n i na jej zapisach o wartościach domyślnych. Część funkcji, o których wspomniałem, wymaga planu płatnego, a część działa wyłącznie przy hostowaniu u siebie. Jeśli chcesz przejść przez to raz, zamiast zbierać wiedzę z dokumentacji, napisz do mnie - odpowiadam zwykle tego samego dnia.

Robisz coś podobnego u siebie?Napisz do mnie

Masz proces, który zjada tydzień pracy? Odzyskajmy ten tydzień.

Napisz do mnie