Postando isso porque me custou algumas horas e falha silenciosamente, que é a pior combinação. Se você rotear algo importante através de um nó IF ou Switch em um booleano, vale dez minutos do seu tempo.
Existem alguns problemas abertos e tópicos de fórum descrevendo esse comportamento sem uma causa raiz anexada. Isso é o que descobri.
O sintoma
Eu tinha um nó Switch decidindo se deveria enviar um alerta. A saída do nó upstream parecia assim:
{ “shouldEscalate”: true }
Condição do Switch: value:
{{ $(‘Extract Response’).first().json.shouldEscalate }}
operador: Boolean → is true
Toda execução roteiou false. Nenhum erro. Execução relatada como sucesso. O alerta simplesmente nunca disparou.
O que não era
Eu perdi tempo com as hipóteses erradas primeiro, então aqui estão para economizar seu tempo:
• Não .first() vs .item — Eu verifiquei
• Não é um problema de multi-run/item-lineage
• Não é o nó upstream produzindo o valor errado
Provei o último deixando um nó Set diretamente antes do Switch que emitiu o valor bruto mais seu tipo: { “val”: true, “type”: “boolean”, “runs”: 1 }
Booleano genuíno. Execução única. Valor correto chegando no nó. E o Switch ainda assim o enviou como false.
A causa real
n8n renderiza a saída da expressão {{ }} como texto. Portanto, um booleano true real chega no operador como a string “true” — e se houver espaço em branco ou uma quebra de linha no campo de parâmetro após o }} de fechamento (muito fácil de introduzir ao colar), você obtém "true ".
O operador Boolean rigoroso obtém "true ", que não é um booleano, e a comparação falha. Silenciosamente, na direção false.
Eventualmente o nó o apresentou literalmente: Wrong type: 'true ’ is a string but was expecting a boolean
Por que as correções óbvias não funcionaram
Tentei converter dentro da expressão:
{{ String($(‘Extract Response’).first().json.shouldEscalate).trim().toBoolean() }}
Ainda falhou. O espaço em branco não está dentro da expressão — é introduzido após }} durante a própria renderização do n8n. Nada que você faça dentro das chaves pode alcançá-lo.
Alternar “Convert types where required” muda o modo de falha em vez de corrigi-lo. No meu caso, uma configuração roteiou tudo como true e a outra roteiou tudo como false. Ambas estão erradas; uma é apenas mais aparente.
A correção que funciona
Deixe de comparar o booleano. Emita uma palavra-chave explícita e corresponda ao texto:
value: {{ $(‘Extract Response’).first().json.shouldEscalate ? “ESCALATE” : “NORMAL” }}
operador: String → contains
match: ESCALATE
convert types: off
"ESCALATE " ainda contém “ESCALATE”. "NORMAL " não contém em nenhum dos casos. O espaço em branco à direita torna-se inofensivo em vez de fatal.
Verificado em ambas as direções no mesmo build — condição true roteia true, condição false roteia false. Vale fazer ambas; testar apenas a direção que você espera é meio teste, e esse bug é especificamente capaz de passar em uma direção enquanto falha na outra.
A versão geral
Se um nó Switch ou IF está tomando uma decisão que realmente importa — alertar, escalar, gating de conformidade, qualquer coisa onde silenciosamente tomar o ramo errado é caro — não a roteie em um booleano bruto. Renderize uma string sentinela e corresponda a ela.
„O modo de falha aqui não é um erro. É uma execução verde que fez a coisa errada.