
Como reportar bugs de modo que eles realmente sejam corrigidos
Relatar um bug de forma eficaz exige mais do que descrever um sintoma: é preciso transformar uma falha aparentemente aleatória em uma evidência reproduzível, localizar o componente responsável e fornecer aos mantenedores informações suficientes para agir. O processo apresentado parte de um caso em que um serviço de produção registrava milhares de vezes a mensagem LEAK: ByteBuf.release() was not called before it's garbage-collected.
Assuma primeiro que o problema é seu
A investigação deve começar pela hipótese de que o erro está no próprio código. Isso evita atribuir prematuramente a falha a uma biblioteca e, se a hipótese estiver correta, permite corrigir o problema diretamente. No caso descrito, a mensagem sugeria um vazamento de memória, mas o comportamento parecia aleatório porque o Netty só informa o vazamento quando o coletor de lixo recolhe o buffer. Assim, um vazamento contínuo aparecia nos registros em rajadas.
Para tornar o comportamento determinístico, a reprodução executava cem solicitações concorrentes e chamava System.gc() sempre que uma delas falhava. O autor ressalta que isso nunca seria apropriado em produção, mas pode funcionar como um holofote em uma reprodução controlada. Em seguida, ele aplicou às versões da dependência uma estratégia semelhante ao git bisect: manteve o mesmo aplicativo, SDK e demais condições e procurou a fronteira entre a versão que funcionava e a que falhava. O resultado foi claro: reactor-netty 1.1.23 permanecia limpo, enquanto a 1.1.24 apresentava o vazamento.
O próximo passo foi reduzir o caso a um repositório público e mínimo. A reprodução virou um projeto Gradle com um único teste e versões fixadas, sem os dados privados e a complexidade do serviço original. Isso permitia demonstrar que a falha não estava no aplicativo e, depois, verificar diretamente se a correção eliminaria o problema.
Leve a evidência ao responsável certo
O primeiro relatório foi aberto no reactor-netty, porque a comparação entre versões apontava para ele. O projeto encerrou a questão explicando que não era o componente responsável. Essa resposta direcionou a investigação para o Azure SDK para Java, construído sobre o reactor-netty.
Também foi útil investigar o histórico. Um problema registrado cinco meses antes mencionava uma mudança no ciclo de vida das conexões introduzida na versão 1.1.24. O Azure havia adicionado uma proteção que fez a exceção desaparecer, mas o buffer continuou vazando; a alteração tornou o bug menos visível, sem eliminá-lo. Relacionar esse histórico ao comportamento atual ajudou a acelerar a análise.
Escreva para quem vai corrigir
Um bom relatório deve conter uma afirmação objetiva com as versões envolvidas, o histórico relevante, o rastreamento completo, registros editados para remover informações privadas e um repositório com a reprodução. Também deve declarar limitações do teste, como a chamada forçada ao coletor de lixo, e separar claramente fatos de hipóteses.
Nos comentários, responder às perguntas do mantenedor com honestidade é tão importante quanto o relatório inicial. Quando perguntado sobre ocorrências durante retentativas, o autor explicou o que sabia e o que não podia confirmar. Um dia depois, foi publicada uma correção. Ele a verificou na reprodução, acompanhou sua liberação, atualizou o serviço em produção e pôde reativar os alertas. A conclusão é que bons relatos dependem sobretudo de tempo, investigação e disposição para fornecer ao mantenedor as informações que só o usuário do sistema consegue observar.