---
title: "Dynamic Filter Troubleshooting Guide"
slug: "dynamic-filter-troubleshooting-guide"
description: "Runbook de troubleshooting do filtro dinamico, cobrindo payload invalido, ranges, schema desatualizado, persistencia local e falhas comuns entre table, dynamic-fields e metadata-starter."
doc_type: "troubleshooting"
document_kind: "runbook"
component: "table"
category: "troubleshooting"
audience:
  - "host"
  - "frontend"
  - "backend"
  - "ops"
level: "advanced"
status: "active"
owner: "praxis-ui"
tags:
  - "dynamic-filter"
  - "troubleshooting"
  - "FILTER_PAYLOAD_INVALID"
  - "schema"
  - "range"
order: 32
icon: "healing"
toc: true
sidebar: true
search_boost: 1.2
reading_time: 20
estimated_setup_time: 35
version: "1.0"
related_docs:
  - "dynamic-filter-payload-contract"
  - "dynamic-filter-range-filters-guide"
  - "dynamic-filter-host-integration-guide"
  - "dynamic-filter-backend-contract-cheatsheet"
keywords:
  - "FILTER_PAYLOAD_INVALID"
  - "schemaOutdated"
  - "metaChanged"
  - "schemaStatusChange"
source_of_truth:
  - "projects/praxis-table/src/lib/components/praxis-filter/praxis-filter.component.ts"
  - "../praxis-metadata-starter/src/main/java/org/praxisplatform/uischema/rest/exceptionhandler/GlobalExceptionHandler.java"
  - "../praxis-metadata-starter/src/main/java/org/praxisplatform/uischema/filter/range/RangePayloadNormalizer.java"
  - "../praxis-metadata-starter/src/main/java/org/praxisplatform/uischema/filter/specification/GenericSpecificationsBuilder.java"
last_updated: "2026-03-07"
---

# Dynamic Filter Troubleshooting Guide

## Objetivo

Fornecer um runbook direto para diagnosticar e corrigir problemas recorrentes do filtro dinâmico em produção e em integração local.

## Pré-requisitos

- Conhecimento básico do pipeline `PraxisFilter -> payload -> metadata-starter`.
- Acesso ao payload enviado pelo host e à resposta HTTP do backend.
- Familiaridade com `related_docs` desta trilha.

## Operational Response

Ao investigar um incidente no filtro, siga esta ordem:

1. validar o payload efetivamente enviado pelo host;
2. confirmar se o schema do filtro está atualizado;
3. verificar se houve normalização ou rejeição de range no backend;
4. checar persistência local e preferências reaplicadas;
5. revisar `controlType` inline e overrides de metadata.

```mermaid
flowchart TD
  incident["Incident in dynamic filter"] --> payload["Inspect payload sent by host"]
  payload --> schema["Validate current schema and drift"]
  schema --> range["Check range normalization and backend rejection"]
  range --> persistence["Inspect local persistence and restored state"]
  persistence --> inline["Review inline controlType and metadata overrides"]
```

## Sintoma: `400 FILTER_PAYLOAD_INVALID`

### Causa provável

O backend rejeitou o payload durante normalização ou construção da specification.

### Onde olhar

- `GlobalExceptionHandler`
- `RangePayloadNormalizer`
- `GenericSpecificationsBuilder`

### Casos típicos

- payload escalar de range;
- lista com mais de dois limites;
- `BETWEEN_EXCLUSIVE` sem dois limites válidos;
- alias conflitante para o mesmo range;
- tipo incompatível com a operação (`LIKE` com valor não textual, `IN` sem lista etc.).

### Resposta esperada

HTTP `400` com `errors[].properties.code = FILTER_PAYLOAD_INVALID`.

## Sintoma: range não filtra ou filtra errado

### Causa provável

O shape enviado não respeita o contrato ou foi interpretado de maneira diferente da esperada.

### Checklist

1. O campo backend usa operação `BETWEEN`, `BETWEEN_EXCLUSIVE`, `NOT_BETWEEN` ou `OUTSIDE_RANGE`?
2. O frontend enviou lista canônica ou objeto canônico?
3. Há `null` explícito preservando upper-only ou lower-only?
4. Existe mistura de aliases como `from` e `minPrice` ao mesmo tempo?

### Ação

Compare o payload com o guia de ranges antes de tentar “corrigir no controller”.

## Sintoma: label conflita com icone, prefixo ou sufixo

### Causa provável

Campos Material `fill`/`outline` com `prefixIcon`, `suffixIcon`, `clearButton`,
datepicker toggle, simbolo de moeda, seletor de cor ou outros
`matPrefix`/`matSuffix` podem exibir o label em repouso sobreposto ou desalinhado.

Esse comportamento vem da propria geometria do `mat-form-field`: em `fill` e
`outline`, o label em repouso e o valor do input nao usam o mesmo alinhamento. O
Angular Material recomenda `floatLabel="always"` nesses casos.

### Onde olhar

- metadata efetiva do campo no filtro avancado;
- `alwaysVisibleFieldMetadataOverrides`;
- politica global aplicada pelo `praxis-filter` para materializar campos de filtro;
- `metadata.materialDesign.floatLabel`;
- `metadata.materialDesign.subscriptSizing`.

### Ação

Configure a metadata do campo ou a politica global do filtro:

```json
{
  "materialDesign": {
    "floatLabel": "always",
    "subscriptSizing": "dynamic"
  }
}
```

Nao corrija deslocando label, prefixo, sufixo ou notch por CSS local. Esse tipo
de patch acopla o host a detalhes internos do Angular Material e tende a quebrar
em upgrades.

## Sintoma: campo inline não aparece na barra compacta

### Causa provável

O host pode ter aplicado opt-out para a variante inline ou o campo não foi promovido corretamente para `alwaysVisibleFields`.

### Onde olhar

- `alwaysVisibleFields`
- `alwaysVisibleFieldMetadataOverrides`
- flags `useInline*Variant`
- catálogo inline canônico

### Ação

Confirme:

- se o nome do campo existe no schema;
- se a variante inline está habilitada;
- se o `controlType` é o nome canônico publicado;
- se o campo deveria mesmo estar na toolbar e não apenas no avançado.

## Sintoma: schema mudou e o filtro ficou inconsistente

### Sinais

- `schemaStatusChange` emitindo `outdated: true`
- comportamento divergente entre o schema atual e o estado local persistido

### Causa provável

O schema do backend mudou, mas o estado local ou as preferências ainda refletem a versão antiga.

### Ação

1. observar `metaChanged` e `schemaStatusChange`;
2. reconciliar schema quando necessário;
3. limpar persistência local se o contrato mudou estruturalmente;
4. revalidar `alwaysVisibleFields` e overrides.

## Sintoma: filtro parece “preso” ou restaura estado inesperado

### Causa provável

Persistência local ativa com `filter-dto:<key>` e `filter-config:<key>`.

### Ação

- revisar o `persistenceKey`;
- limpar config e DTO persistidos;
- confirmar se o ambiente de teste não está herdando estado anterior.

## Sintoma: tags não funcionam como esperado

### Causa provável

`allowSaveTags` não está habilitado, ou a expectativa do produto sobre tags não está alinhada com o runtime.

### Ação

- confirmar `allowSaveTags`;
- revisar se as tags são só visualização ou presets operacionais;
- evitar documentar tags como comportamento universal do filtro.

## Sintoma: comportamento diferente entre modal e drawer

### Causa provável

Configuração distinta em `advancedOpenMode` e/ou `advancedClearButtonsEnabled`.

### Ação

Verificar:

- modo de abertura atual;
- clear buttons avançados;
- densidade e largura dos campos no contexto real.

## Matriz rápida de causa e correção

| Sintoma | Causa mais provável | Correção inicial |
| --- | --- | --- |
| `400 FILTER_PAYLOAD_INVALID` | payload incompatível com operação | revisar payload e contrato backend |
| range vazio “vira filtro” | serialização indevida no host | remover objeto vazio antes do envio |
| inline não aparece | flag inline ausente ou campo não pinado | revisar settings editor |
| schema fica desatualizado | drift entre backend e estado local | reconciliar schema e limpar persistência |
| filtro restaura valor antigo | `persistenceKey`/storage reaplicando estado | limpar `filter-dto:*` e `filter-config:*` |

## Regra operacional final

Nunca trate bug de filtro só como problema de UI.

No Praxis, a falha pode estar em qualquer uma destas camadas:

- metadata/schema;
- runtime do `praxis-filter`;
- configuração do host;
- payload enviado;
- normalização do `metadata-starter`;
- specification backend.
