Meu fluxo de trabalho funciona perfeitamente, mas quando anexo memória ao LLM (OpenAI), que está quase no meio do fluxo de trabalho, muitos nós de código que estão antes do nó http (para enviar carga útil ao painel)
Estou enfrentando um problema grave de desempenho em que meus nós de código congelam e eventualmente expiram, mas apenas quando a memória do LLM está presente no fluxo de trabalho.
Meu fluxo de trabalho processa dados JSON recebidos usando alguns nós de código padrão (realizando limpeza e validação de dados). Mais adiante no fluxo de trabalho, tenho um nó LLM (OpenAI) com um componente de memória anexado.
Quando executo o fluxo de trabalho sem a memória do LLM, tudo é executado perfeitamente e instantaneamente. No entanto, no momento em que anexo memória ao LLM, vários nós de código que são executados antes de um nó de solicitação HTTP ficam presos em um travamento infinito.
Qual é a mensagem de erro (se houver)?
Algo assim: não há mais mensagem de erro, apenas execução infinita. Erro:
Execução da tarefa expirou após 300 segundos
O executor de tarefas demorou muito em esta tarefa, portanto foi suspeito de estar sem resposta e foi reiniciado, e a tarefa foi abortada. Você pode tentar o seguinte: 1. Otimize seu script para evitar tarefas de execução longa, por exemplo, processando dados em lotes menores. 2. Certifique-se de que todos os caminhos do seu script possam terminar, ou seja, nenhum loop infinito. 3. Se sua tarefa pode razoavelmente levar mais de 300 segundos, aumente o tempo limite usando a variável de ambiente N8N_RUNNERS_TASK_TIMEOUT.
é uma proteção específica do n8n. Significa que o código JavaScript dentro de seus nós de Código está sendo executado por mais de 300 segundos, fazendo com que o n8n Task Runner assuma que ele está preso em um loop infinito ou processando uma tarefa impossível, então o encerra forçadamente.
Como isso apenas acontece quando você anexa Memória ao LLM, o componente de Memória está fundamentalmente alterando a estrutura de dados, tamanho ou comportamento dos dados fluindo para seus nós de Código a jusante.
Quando a Memória está anexada, o nó LLM (ou a chain/agent da qual faz parte) pode estar passando o histórico completo da conversa ou um grande objeto de estado de memória para o fluxo de dados principal, em vez de apenas a resposta final da IA.
O Problema: Se seus nós de Código estão tentando processar, limpar ou fazer JSON.stringify() de uma entrada que agora contém centenas ou milhares de mensagens históricas, facilmente excederá o timeout de CPU de 300 segundos.
A Solução: Você precisa reduzir os dados apenas para o que o dashboard precisa imediatamente após o nó LLM.
Adicione um nó de Código temporário logo após o nó LLM com este código para ver o que está sendo passado:
// Check how many items and the size of the data
const items = $input.all();
console.log("Total items:", items.length);
console.log("First item keys:", Object.keys(items[0].json));
return items;
Se você vir um enorme array messages ou objeto de memória, atualize seus nós de Código a jusante para extrair apenas o campo específico que você precisa (por ex., item.json.message.content ou item.json.text) e descarte o resto antes do processamento.
Objetos de Memória no n8n (especialmente ao lidar com integrações do LangChain) às vezes podem conter referências circulares (onde um objeto referencia a si mesmo).
O Problema: Se seus nós de Código usam JSON.stringify($input.all()) ou passam o objeto de entrada inteiro para uma função de análise personalizada, uma referência circular pode fazer com que o mecanismo JavaScript entre em um loop infinito tentando serializar o objeto, resultando no timeout de 300s.
A Solução: Nunca faça stringify de todo o $input ou $input.all() se contiver saídas de LLM/Memória. Sempre extraia os valores primitivos de string primeiro:
// BAD: Can hang if circular references exist
// const payload = JSON.stringify($input.all());
// GOOD: Extract only the primitive data you need
const cleanData = $input.all().map(item => ({
response: item.json.message?.content || item.json.text,
// add other specific fields here
}));
const payload = JSON.stringify(cleanData);
Se seus nós de Código usam loops while, funções recursivas ou métodos .reduce() que dependem da estrutura do JSON recebido, a adição de Memória pode ter alterado essa estrutura.
O Problema: Por exemplo, se seu código tem um loop while que processa um array até estar vazio, mas o componente de Memória acidentalmente injeta um array aninhado que continua se regenerando ou não atende à condição de saída, o loop rodarará para sempre.
A Solução: Revise todos os loops while em seus nós de Código. Adicione um “contador de segurança” para forçá-los a quebrar se excederem um número razoável de iterações:
let safetyCounter = 0;
while (myCondition && safetyCounter < 1000) {
// your logic
safetyCounter++;
}
Como disse, a memória anexada ao LLM está no meio do fluxo de trabalho.
E uma vez que anexei a memória, enfrentei problemas com vários nós de código, e alguns nós de código estão no início do fluxo de trabalho (antes mesmo do nó de memória do llm ser executado).
Sem memória, o fluxo de trabalho é concluído sem problemas, mas com memória, o mesmo fluxo de trabalho começa a ter problemas no nó de código
Oi @sherazbintahir
Os nós de Código travando puramente pela presença de um subnó, incluindo aqueles que são executados antes dele, é o executor de tarefas falhando em resolver o tipo desse subnó. Qualquer coisa que faz um nó de Código pedir ao processo principal contexto extra, uma referência $('Node Name') ou $node["Node Name"] ou um require() de um módulo externo, envia o executor de volta para reconstruir o fluxo de trabalho, e um tipo de subnó que não consegue resolver deixa essa solicitação sem resposta até que o timeout de 300s encerre. Os logs do seu container n8n mostrarão “Unrecognized node type: …” no momento em que ele trava.
Reescreva esses nós de Código para usar apenas $input e $json, e mova qualquer coisa que precisem de um nó anterior para o caminho principal com um nó Set primeiro. Desligar o executor não é uma opção na versão 2.11.3, N8N_RUNNERS_ENABLED foi descontinuado desde a versão 2.0 e toda execução de nó de Código é executada em um executor.
Obrigado, vai ajudar muito. Mas estou confuso aqui porque meu workflow completo (120+ nós) funciona perfeitamente sem nenhum erro, mas quando anexo a memória com LLM (nó de agente IA com OpenAI + memória) enfrento este problema.
Para mais informações, no workflow sem memória, uso o nó OpenAI diretamente. E não estou enfrentando este problema em todos os nós de código, mas em alguns.
Caixa Amarela: Onde estou anexando memória com LLM.
Pontos Vermelhos: Onde estou enfrentando problemas nos nós de código. A maioria dos nós são aqueles em que estou construindo/preparando payload para enviar ao dashboard.
Oi @sherazbintahir Isso não é lentidão, seus nós Code estão em deadlock, não ocupados.
Desde a v2.0, todos os nós Code rodam em um processo task runner separado. Se um script usa apenas input/input / input/json, recebe um payload reduzido e executa instantaneamente. Mas se usa (′NodeName′)'or'('Node Name') ou (′NodeName′)'or'node['Node Name'], o runner precisa requisitar o workflow serializado completo de volta do n8n e reconstruí-lo, e isso requer resolver todo tipo de nó na tela, sub-nós inclusos. Anexe o sub-nó memory e o runner encontra um tipo que não consegue resolver, a requisição nunca retorna, e seu nó Code aguarda eternamente até que o watchdog de 300s o encerre. Mesmo que #20752.
Isso também explica por que apenas alguns de seus nós Code quebram — os que funcionam são aqueles que nunca acessam fora de sua própria entrada.
Você pode verificar duas coisas?
Execute com memory anexado e procure em seus logs:
Abra um dos nós Code congelados — contém $('...') ou $node[...] em algum lugar?
Se sim para ambos, a correção é rápida: coloque um nó Set na frente dele e passe o valor como uma expressão (={{ $('Clean JSON').first().json.config }} — expressões em nós normais rodam no processo principal e não são afetadas), depois leia de $input dentro do nó Code. Memory fica exatamente onde está.
Poste o que a linha de log diz e darei a reescrita exata para seu nó.
@sherazbintahir A variável não é memória — é o node swap. Sem memória você usou o node OpenAI simples. Para anexar memória você teve que mudar para o AI Agent, uma raiz de cluster LangChain que puxa sub-nodes para a tela (Chat Model, Memory, sua ferramenta search_workwell_memory). O node OpenAI funciona bem no task runner; sub-nodes do Agent frequentemente não funcionam.
Por que apenas alguns nodes Code: desde a v2.0 todos os nodes Code são executados em um processo runner separado.
Usa apenas $input / $json → payload enxuto, instantâneo. sim (seus nodes de limpeza/validação)
Usa $('Node') / $node['Node'] / $items() — o runner solicita todo o workflow serializado de volta e o reconstrói, o que significa resolver cada tipo de node em sua tela com 120 nodes, incluindo sub-nodes. Um tipo não resolvível — a solicitação nunca retorna — fica pendurada até que o watchdog de 300s seja disparado. não (seus payload builders — os pontos vermelhos)
Note que o sub-node da ferramenta pode causar isso sozinho também: #20752 era postgrestool, #20132 Apify/Perplexity — ali ficou pendurado mesmo que o Agent nunca tivesse sido executado.
Confirme em 30s — deixe a memória anexada, congele um node:
Mescle o node no node Code, depois leia $input.all(). Mais limpo na sua escala.
Coloque o node na frente, resolva valores como expressões: ={{ $('Parse Extraction').first().json.score }} expressões em nodes normais são avaliadas no processo principal, portanto são imunes.
Pule o node Code — construa o corpo JSON diretamente no node HTTP Request com expressões.
Mantenha pairedItem: { item: index } nos itens retornados, ou expressões downstream reintroduzem o problema. A memória permanece anexada nos três casos.
Não ajudará: aumentar N8N_RUNNERS_TASK_TIMEOUT (a espera é ilimitada), ou N8N_RUNNERS_ENABLED=false (ignorado na 2.x).
Pode postar a saída de docker logs -f <n8n-container> | grep -i "unrecognized" enquanto executa com o Agent conectado? Isso mostrará se é a memória ou a ferramenta.