---
title: "NG0500 Hydration Node Mismatch: o conserto de verdade não é ngSkipHydration"
description: "O que o NG0500 Hydration Node Mismatch quer dizer, a lista curta de causas reais (DOM manipulado direto, HTML inválido que o browser normaliza, biblioteca de DOM de terceiro, HTML alterado no caminho), por que o ngSkipHydration é torniquete, e o fix de cada caso."
deck: "`NG0500: Hydration Node Mismatch` quer dizer que o DOM que o Angular montou no cliente não bateu com o HTML que o seu servidor mandou. O conserto popular, o [`ngSkipHydration`](https://angular.dev/guide/hydration), silencia o erro jogando a hydration fora naquele trecho. A doc chama isso de last resort, e trata o componente que quebra como um bug. O NG0500 é um diagnóstico: algo alterou o DOM entre o servidor e o cliente, e quase sempre é um item de uma lista curta."
author: "André Ramos"
url: "https://andreramos.dev/pt/angular/angular-hydration-mismatch-ng0500/"
lang: "pt-BR"
type: "article"
---

# NG0500 Hydration Node Mismatch: o conserto de verdade não é ngSkipHydration

> `NG0500: Hydration Node Mismatch` quer dizer que o DOM que o Angular montou no cliente não bateu com o HTML que o seu servidor mandou. O conserto popular, o [`ngSkipHydration`](https://angular.dev/guide/hydration), silencia o erro jogando a hydration fora naquele trecho. A doc chama isso de last resort, e trata o componente que quebra como um bug. O NG0500 é um diagnóstico: algo alterou o DOM entre o servidor e o cliente, e quase sempre é um item de uma lista curta.

## O erro, e a família

A mensagem abre com `NG0500: During hydration Angular expected ...`. A descrição oficial é precisa: durante a hydration o Angular esperava a estrutura de DOM que ele renderizou e anotou no servidor, mas no cliente a árvore de DOM era diferente. A hydration reaproveita o DOM renderizado no servidor em vez de recriar, então qualquer divergência entre as duas árvores trava o processo.

O NG0500 é o título de uma família, e você pode ter colado um vizinho. NG0501 é siblings faltando, NG0502 um nó faltando, NG0503 projeção de nós de DOM não suportada, NG0504 uma flag de skip-hydration num nó inválido, NG0505 sem info de hydration na resposta do servidor, NG0506 uma aplicação que segue instável, e NG0507 HTML que foi alterado depois do server-side rendering. Todos levam à mesma ideia: o DOM do cliente não é o que o servidor prometeu.

## O que de fato causa

As causas são uma lista curta, e a maioria não é sutil depois que você conhece. A sorrateira é HTML inválido. O browser conserta calado uma marcação malformada, então o servidor manda uma árvore e o browser interpreta outra, e a hydration vê um mismatch que você não causou de propósito.

As outras: código que mexe no DOM direto (APIs nativas, `innerHTML`, `outerHTML`, `appendChild`, mover nós), bibliotecas de terceiro que renderizam no DOM (a doc cita os gráficos do D3), e o `preserveWhitespaces` setado diferente entre o build do servidor e o do cliente.

| Causa | Por que a hydration quebra | Direção do fix |
|---|---|---|
| Aninhamento de HTML inválido | O browser normaliza; a árvore do cliente difere da do servidor | Conserte a marcação pra as duas darem a mesma árvore |
| DOM manipulado direto | innerHTML, appendChild, mover nós muda a árvore | Use binding do Angular ou Renderer2 |
| Biblioteca de DOM de terceiro (D3, etc.) | Ela muta o DOM durante e depois do SSR | Rode só no cliente, depois da hydration |
| preserveWhitespaces inconsistente | Os builds de servidor e cliente emitem whitespace diferente | Alinhe o setting nos dois builds |

*A armadilha do aninhamento inválido (o browser reescreve)*

```html
<!-- Quebra a hydration: o browser tira o <div> de dentro do <p>,
     então a árvore do cliente não bate mais com o HTML do servidor -->
<p>{{ summary }} <div class="badge">{{ status }}</div></p>

<!-- Válido: servidor e cliente interpretam a mesma árvore -->
<p>{{ summary }} <span class="badge">{{ status }}</span></p>
```

## ngSkipHydration é torniquete, não cura

Busque NG0500 e a resposta do topo é `ngSkipHydration`. Funciona, e é esse o problema. O atributo força o Angular a pular a hydration do componente inteiro e dos filhos, então o erro some porque a hydration some naquele trecho. Coloque na raiz e você desligou a hydration do app inteiro, mas seguiu pagando o custo do SSR.

A doc é direta sobre o papel dele: é um last resort, e um componente que quebra a hydration deve ser tratado como bug a consertar. Então, se você for usar, dê escopo no host mais estreito, e trate como [o playbook de SSR e hydration](/pt/angular/ssr-hydration-and-defer-without-guesswork) trata: todo `ngSkipHydration` ganha um dono, um motivo e um plano de remoção, ou vira cicatriz permanente que ninguém tem coragem de mexer.

## Os fixes de verdade, por causa

Aninhamento inválido: conserte a marcação pra o HTML do servidor e o DOM interpretado pelo browser serem a mesma árvore. Um `<div>` dentro de um `<p>`, um `<a>` dentro de um `<a>`, uma `<table>` sem `<tbody>`, esses são os suspeitos de sempre.

DOM manipulado direto: leve pro lado das APIs do Angular, binding, `Renderer2`, o template, pra o framework ser dono da estrutura nos dois lados. Quando você precisa mesmo de uma biblioteca de DOM que pinta depois que a página existe, rode só no cliente com `afterNextRender`, que dispara depois da hydration e nunca no servidor, então não sobra nada pra hydration estranhar.

*Trabalho de DOM só no cliente, depois da hydration*

```ts
// Quebra a hydration: a lib de gráfico muta o DOM no servidor e no
// cliente, e as duas árvores não batem
ngOnInit() { this.renderChart(this.host.nativeElement); }

// Resolvido: rode só no cliente, depois que a hydration termina
private readonly host = inject(ElementRef);
constructor() {
  afterNextRender(() => this.renderChart(this.host.nativeElement));
}
```

## Quando só quebra em produção

Alguns NG0500 passam local e falham só depois do deploy. A regra que a doc declara é que o HTML produzido pelo SSR não pode ser alterado entre o servidor e o cliente. Qualquer coisa no meio que reescreve a resposta quebra isso: um proxy ou CDN que minifica HTML, um edge worker que injeta uma tag, uma camada de segurança que reordena atributos. O servidor renderizou uma árvore, o browser recebeu outra, e o NG0507 é o código explícito pra HTML alterado depois do rendering.

Então, quando o componente está limpo mas o erro é real, olhe o caminho entre o seu servidor e o browser antes de pegar o `ngSkipHydration`. O fix é parar a reescrita, não pular a hydration de um componente que nunca foi o problema.

## Artefato reaproveitável: Depurando o mismatch de hydration NG0500

- Leia qual nó a mensagem nomeia; é ali que a árvore do servidor e a do cliente divergiram.
- Olhe o template atrás de aninhamento de HTML inválido (div em p, a em a, table sem tbody); o browser reescreve.
- Ache o DOM manipulado direto (innerHTML, appendChild, APIs nativas) e leve pra binding do Angular ou Renderer2.
- Pra biblioteca de DOM de terceiro, rode só no cliente com afterNextRender pra ela nunca rodar no SSR.
- Se só falha em produção, cheque proxy ou CDN alterando o HTML no caminho (NG0507).
- Use ngSkipHydration só como last resort, com escopo no host mais estreito, com dono e plano de remoção.

## Perguntas frequentes

### O que quer dizer o NG0500 Hydration Node Mismatch?

Na hydration, o Angular reaproveita o DOM que o seu servidor renderizou. O NG0500 quer dizer que a árvore de DOM no cliente ficou diferente da que o servidor produziu, então o Angular não consegue casar as duas. Algo mudou a estrutura entre o servidor e o cliente.

### É só adicionar o ngSkipHydration?

Só como last resort. A doc diz que ele força o Angular a pular a hydration do componente e dos filhos, então você mantém o custo do SSR mas perde a hydration naquele trecho, e chama de bug um componente que quebra a hydration. Se usar, dê escopo estreito e um plano de remoção.

### Por que o NG0500 acontece com template que parece válido?

O aninhamento de HTML inválido é a surpresa comum: um `<div>` dentro de um `<p>`, um `<a>` dentro de um `<a>`, ou uma `<table>` sem `<tbody>`. O browser reescreve a marcação calado, então o DOM interpretado não bate mais com o HTML do servidor.

### Funciona local mas o NG0500 estoura em produção. Por quê?

O HTML do SSR não pode ser alterado entre o servidor e o cliente. Um proxy ou CDN que minifica HTML, ou uma camada de edge que injeta ou reordena marcação, muda a árvore que o browser recebe. O NG0507 é o código explícito pra HTML alterado depois do rendering.

## Fontes consultadas

- https://angular.dev/errors/NG0500
- https://angular.dev/guide/hydration
- https://angular.dev/guide/incremental-hydration
- https://angular.dev/guide/ssr
- https://angular.dev/api/core/afterNextRender
- https://blog.angular.dev/announcing-angular-v21-57946c34f14b

## Leia também

- [SSR, hydration e @defer sem chute](https://andreramos.dev/pt/angular/ssr-hydration-and-defer-without-guesswork/)
- [NG0100 ExpressionChangedAfterItHasBeenCheckedError: por que ele aparece no Angular zoneless](https://andreramos.dev/pt/angular/expressionchanged-error-zoneless-angular/)
- [O código que quebra quando Angular fica zoneless](https://andreramos.dev/pt/angular/code-that-breaks-when-angular-goes-zoneless/)
