Qualquer engenheiro que já manteve um emissor de NF-e (Modelo 55) ou NFC-e (Modelo 65) sob carga pesada conhece a seguinte sequência de eventos: a aplicação envia o lote para o webservice NFeAutorizacao4 da SEFAZ, a conexão sofre um ETIMEDOUT ou ECONNRESET aos 15 segundos, a fila de mensageria faz o retry automático da nota e, na segunda tentativa, a SEFAZ responde com Rejeição 539: Duplicidade de NF-e, com diferença na Chave de Acesso.
Pior ainda: em dias de instabilidade ou pico de vendas como a Black Friday, um retry mal projetado pode chavear a nota para contingência (SVC-AN ou SVC-RS) depois que a SEFAZ de origem já havia recebido e autorizado o primeiro envio silenciosamente — gerando dupla autorização fiscal ou buracos na sequência numérica da série que obrigam a contabilidade a inutilizar faixas às pressas.
A única forma de erradicar a Rejeição 539 na NF-e e NFC-e é persistir o artefato completo de emissão (número nNF, série, tpEmis, código aleatório cNF de 8 dígitos, chave de 44 posições e XML assinado) com lock pessimista (FOR UPDATE) ANTES do envio SOAP, reutilizando exatamente a mesma chave em qualquer retry e reconciliando via NFeConsultaProtocolo4.
Na release v0.56.54 / w0.33.52 da Notaas, nós redesenhamos toda a camada de guarda de retry, auto-reconciliação SEFAZ e inutilização de numeração (POST /api/v1/nfe/inutilizar). Neste artigo, vou abrir a arquitetura exata que implementamos nos nossos workers.
Quando uma requisição para a SEFAZ sofre timeout de leitura (
ETIMEDOUT), você não sabe se a nota morreu no caminho ou se já foi autorizada lá dentro. Gerar um novocNFaleatório no retry é pedir para tomar Rejeição 539.
Por que a Rejeição 539 acontece em filas assíncronas (RabbitMQ, BullMQ, SQS)
A Chave de Acesso de 44 dígitos de uma NF-e ou NFC-e é formada por:
cUF (2) + AAMM (4) + CNPJ (14) + mod (2) + serie (3) + nNF (9) + tpEmis (1) + cNF (8) + cDV (1).
Na maioria dos emissores tradicionais, quando um worker consome uma mensagem da fila para emitir a nota de número 1050 na série 1, ele executa um pipeline linear em memória:
- Sorteia um código numérico aleatório de 8 dígitos (
cNF = Math.floor(Math.random() * 90000000) + 10000000). - Monta a chave de 44 dígitos, gera o XML
<NFe>e assina digitalmente com o certificado A1. - Abre o socket TLS e dispara o
NFeAutorizacao4para a SEFAZ. - Salva a chave e o protocolo no banco de dados após a resposta.
O problema fatal está na ordem entre os passos 3 e 4. Se a SEFAZ processar e autorizar a nota 1050 com cNF = 48291034, mas a conexão TCP cair antes do seu worker ler o XML de retorno (ECONNRESET), o worker lança exceção e devolve a mensagem para a fila (nack).
Quando o retry roda 5 segundos depois para a mesma nota 1050, o código sorteia outro cNF aleatório (digamos, cNF = 91827364), gerando uma nova chave de 44 dígitos para o mesmo CNPJ + mod + serie + nNF. Ao bater na SEFAZ, o autorizador estadual detecta que a nota 1050 já existe com outra chave e devolve:
cStat 539 - Rejeição: Duplicidade de NF-e, com diferença na Chave de Acesso [chNFe: 352610...][nProt: 135260...].
A arquitetura de 4 camadas contra Rejeição 539/204 que implementamos na Notaas
Para resolver esse problema na raiz em ambiente distribuído (com múltiplos workers rodando em paralelo no Docker Swarm), nós estruturamos o nfe-retry-guard da Notaas em quatro barreiras determinísticas:
⚡ Pipeline de Emissão NF-e/NFC-e Idempotente (Zero Erro 539):
- 1. Lock Pessimista e Persistência Pré-SOAP (
claimOrCreateEmissionArtifact): ExecutaSELECT ... FOR UPDATEna invoice, alocan_nf, geracNF, monta e assina o<NFe>completo (incluindo QR Code na NFC-e) e fazCOMMITno banco antes de chamar a SEFAZ.- 2. Reuso Estrito do Artefato no Retry (
inspectStoredEmissionArtifact): Se a tentativa anterior sofreu timeout, o retry lê achave_acessoe onfe_xmljá assinados do banco e reenvia exatamente o mesmo payload.- 3. Guarda de Contingência SVC (
canSwitchToSvcOnNetworkError): Só permite chavear automaticamente paraSVC-AN/SVC-RS(tpEmis6/7) em falhas pré-conexão (ECONNREFUSED,ENOTFOUND) oucStat 108/109, nunca após timeout de leitura.- 4. Auto-Reconciliação (
reconcileSefazAuthorization): Ao detectarcStat 204ou539(ou recibo pendente), extrai a chave/protocolo ou consultaNFeConsultaProtocolo4, reconstrói o<nfeProc>autorizado e gera o DANFE automaticamente.
Camada 1 e 2: Persistência do XML assinado antes da rede
Ao gravar n_nf, serie, tp_emis, chave_acesso e nfe_xml assinado no PostgreSQL antes de abrir a conexão HTTP com a SEFAZ, garantimos que o código aleatório cNF nunca mude entre tentativas da mesma nota.
Além disso, se dois workers receberem entrega duplicada da fila ao mesmo tempo, o SELECT * FROM nfe_invoices WHERE id = $1 FOR UPDATE serializa o acesso e impede que uma nota que já entrou em status = 'issued' ou status = 'error' seja retransmitida acidentalmente.
Camada 3: Quando é seguro (e quando é perigoso) chavear para SVC-AN / SVC-RS
Como detalhamos no nosso artigo sobre contingência automática SVC-AN e SVC-RS na NF-e, mudar o tpEmis de 1 (Normal) para 6 ou 7 (SVC) altera o 35º dígito da Chave de Acesso.
Por isso, nossa função canSwitchToSvcOnNetworkError() diferencia rigorosamente dois tipos de erro de rede:
- Falha Pré-Conexão (
ECONNREFUSED,ENOTFOUND,EHOSTUNREACH) ou SEFAZ Paralisada (cStat 108/109): Nenhum byte do XML foi entregue ao servidor de origem. É 100% seguro regerar o artefato comtpEmis = 6/7e emitir via SVC. - Falha Pós-Envio (
ETIMEDOUT,ECONNRESETdurante leitura): O XML pode ter sido processado na SEFAZ normal. O worker mantém o artefato original (tpEmis = 1) e consulta o protocolo antes de qualquer decisão.
Camada 4: Auto-Reconciliação com NFeConsultaProtocolo4
E se a primeira tentativa realmente foi autorizada na SEFAZ durante um timeout de rede? Quando o segundo envio bate na SEFAZ com a mesma chave (retornando cStat 204 - Duplicidade de NF-e) ou se houver divergência (cStat 539), nossa rotina reconcileSefazAuthorization() entra em ação:
- Extrai a chave e o protocolo informados pela própria SEFAZ na mensagem de rejeição (
extractSefazDuplicityHints) ou dispara uma consulta ao webserviceNFeConsultaProtocolo4. - Quando o retorno confirma
cStat = 100(Autorizado o uso da NF-e) ou150com<protNFe>válido, a Notaas acopla o<protNFe>ao<NFe>assinado para montar o<nfeProc versao="4.00">, salva o PDF do DANFE no storage, marca a nota comoissuede dispara o webhooknota.autorizadapara o seu ERP — transformando o que seria um erro crítico em uma emissão concluída de forma transparente!
E quando um número realmente precisa ser inutilizado? (POST /api/v1/nfe/inutilizar)
Mesmo com reciclagem inteligente de numeração (nfe_numeros_liberados), existem cenários operacionais — como migração de um ERP antigo para a Notaas ou descarte manual de uma tentativa que avançou na numeração — em que a legislação exige a Inutilização de Numeração de NF-e/NFC-e (NFeInutilizacao4, retorno cStat 102).
Para que você não precise montar e assinar o XML < inutNFe versao="4.00"> na mão (cujo atributo Id exige exatamente ID + cUF + ano (2) + CNPJ + mod + serie (3) + nNFIni (9) + nNFFin (9)), disponibilizamos o endpoint direto POST /api/v1/nfe/inutilizar:
curl -X POST "https://platform.notaas.com.br/api/v1/nfe/inutilizar" \
-H "Authorization: Bearer ntaas_live_sua_api_key" \
-H "Content-Type: application/json" \
-d '{
"modelo": 55,
"serie": 1,
"numeroInicial": 1048,
"numeroFinal": 1049,
"justificativa": "Quebra de sequencia numerica durante migracao de sistema emissor"
}'
O endpoint valida a justificativa (mínimo de 15 caracteres exigido pela SEFAZ), verifica se não existe nenhuma nota autorizada naquela faixa dentro do seu projeto, assina o evento com o certificado A1, transmite para a SEFAZ da UF correspondente (incluindo SVRS e SVAN), persiste o XML <ProcInutNFe> e já remove esses números da fila de reciclagem para que nunca mais sejam reutilizados:
{
"success": true,
"data": {
"id": "inut_99281726",
"cStat": 102,
"xMotivo": "Inutilizacao de numero homologado",
"protocolo": "135260009182736",
"modelo": 55,
"serie": 1,
"numeroInicial": 1048,
"numeroFinal": 1049
}
}
Se você também lida com operações interestaduais complexas ou devoluções de mercadorias, vale conferir nosso guia sobre como emitir NF-e com ICMS ST e devolução sem Rejeição W16-10 e como preencher Pedido de Compra (xPed e nItemPed) via API.
Emita NF-e e NFC-e com resiliência de nível bancário
Pare de apagar incêndios de duplicidade na SEFAZ ou perder horas reconciliando notas que deram timeout.
- Plano Free (R$ 0/mês): 20 notas fiscais gratuitas por mês em Produção (1 CNPJ) + até 5 projetos simultâneos em Homologação via Org API.
- Plano Dev (R$ 99/mês): 500 notas/mês + até 3 CNPJs em Produção.
- Plano SaaS Pro (R$ 249/mês): 2.000 notas/mês + CNPJs ilimitados em Produção e Homologação.
👉 Criar Conta Gratuita na Notaas · Explorar Documentação NF-e / NFC-e

