4 pontos por GN⁺ 2025-08-08 | 1 comentários | Compartilhar no WhatsApp
  • Compartilhamento de uma lista de conhecimentos amaldiçoados adquiridos durante o desenvolvimento do Immich
  • Organização de problemas inesperados encontrados em diferentes ambientes de software e infraestrutura
  • Menciona questões de ferramentas e linguagens, incluindo metadados EXIF, tratamento de espaços em branco em YAML, PostgreSQL
  • Alguns problemas se conectam diretamente à segurança, compatibilidade de plataforma e dependências de código aberto
  • Foca em casos reais e causas que desenvolvedores devem ficar atentos

Visão geral

O time de desenvolvimento do Immich divulgou uma lista de conhecimentos amaldiçoados que não quer mais precisar reaprender durante o projeto. Trata-se de uma relação de armadilhas e problemas inesperados encontrados diretamente em diversas ferramentas, linguagens e plataformas durante o desenvolvimento e operação de serviços reais.

Lista de conhecimento amaldiçoado

  • 4 de junho de 2025

    • O Actions do Zitadel é uma funcionalidade amaldiçoada
    • O recurso de script personalizado oferecido pelo Zitadel é baseado no motor JS, mas mostra limitações por não suportar grupos de captura nomeada em regex
  • 30 de maio de 2025

    • O Microsoft Entra suporta PKCE, mas não documenta isso no documento de descoberta do OpenID
    • Isso causa um problema em que o recurso existente não é detectado no cliente
  • 5 de maio de 2025

    • As informações de tamanho nos metadados EXIF das imagens podem ser diferentes da imagem real
    • Essa diferença pode causar erros em operações de recorte e redimensionamento
  • 1 de abril de 2025

    • O tratamento de espaços em YAML frequentemente se comporta de modo diferente do esperado
    • Por ser sensível à formatação, há risco de interpretação de conteúdo diferente da intenção
  • 20 de setembro de 2024

    • Arquivos ocultos do Windows não são abertos com a flag "w"
    • Combinado com a opção "hide dot files" do SMB, isso aumenta bastante a confusão no listagem e no processamento de arquivos
  • 7 de agosto de 2024

    • Em scripts Bash, é possível haver problema de carriage return (CRLF)
    • Se o Git converter automaticamente LF para CRLF no checkout, isso pode causar erros na execução do script
  • 7 de agosto de 2024

    • No Cloudflare Workers, o fetch aplica http por padrão mesmo quando o https é especificado
    • Isso pode causar problemas de rede, como loops de redirecionamento
  • 21 de julho de 2024

    • O compartilhamento de GPS em mobile remove silenciosamente os dados de GPS das imagens quando o app não tem permissão de localização
    • Impacta a precisão de serviços baseados em localização e a privacidade
  • 3 de julho de 2024

    • O NOTIFY do PostgreSQL funciona apenas dentro de transações
    • Ao usar com socket.io e postgres-adapter, ocorre gravação de WAL a cada 5 segundos, gerando carga
  • 3 de julho de 2024

    • Cada vez que um script npm é executado, é enviada uma solicitação HTTP ao registro npm
    • Portanto, realizar health check via script é ineficiente
  • 28 de junho de 2024

    • Alguns usuários da comunidade JavaScript forçaram a inclusão de cerca de 50 dependências de pacotes sob o pretexto de retrocompatibilidade
    • Todas essas dependências são mantidas pelo mesmo usuário
  • 25 de junho de 2024

    • A implementação do bcrypt usa apenas os primeiros 72 bytes da string
    • Os caracteres após isso são ignorados, tornando senhas longas sem efeito
  • 31 de janeiro de 2024

    • O objeto Date do JavaScript indexa ano e dia a partir de 1, e o mês a partir de 0
    • É uma estrutura fácil de causar confusão
  • 9 de janeiro de 2024

    • Em projetos CommonJS usando a opção --experimental-vm-modules do Node.js anterior à v20.8,
      • ocorre segfault ao carregar novamente módulos CommonJS em módulos ES, fazendo o Node.js crashar
  • 28 de dezembro de 2023

    • O limite de parâmetros do PostgreSQL é 65.535
    • Isso gera limitação de desempenho em inserções em massa com grandes conjuntos de dados
  • 26 de junho de 2023

    • Há APIs da web disponíveis apenas em Secure Contexts
    • Especificamente, APIs como a Clipboard funcionam apenas em ambientes https ou localhost
  • 23 de fevereiro de 2023

    • A implementação do remove do TypeORM afeta os dados de entrada
    • Remove também a propriedade id do objeto original

Conclusão

Esse tipo de conhecimento amaldiçoado aparece com frequência em cenários reais de desenvolvimento e operação de serviços. Para desenvolvedores, mapear previamente as restrições e problemas ocultos por ferramenta, linguagem e ambiente ajuda na resolução eficiente de problemas e no desenvolvimento de serviços mais estáveis.

1 comentários

 
GN⁺ 2025-08-08
Opinião do Hacker News
  • Desde que vi isso pela primeira vez, já gostei bastante. Depois de dar uma olhada no commit de exemplo (aqui), passei a gostar ainda mais. O fato de o ‘conhecimento amaldiçoado’ ficar registrado junto com o código que resolveu o problema é especialmente legal. A primeira coisa que me veio à cabeça foi que esse recurso é necessário em todos os projetos. O log não é apenas catártico; ele transforma problemas chatos em uma experiência de aprendizado positiva. Ao ser exposto publicamente, dá para se identificar com pessoas que passaram pelos mesmos problemas e também pode virar uma ferramenta para evitar que se repitam.

    • Normalmente eu costumo colocar esse tipo de informação diretamente na mensagem do commit. Quando alguém olha uma linha de código e pensa “por que isso foi feito de forma tão ruim? não dava para fazer só ___?”, é útil já ter a explicação ali.
  • Fiquei surpreso com a parte de que “não dá para fazer bind de 65 mil placeholders do PostgreSQL em uma única consulta”. No fim das contas, essa não é uma boa ideia e, por isso, é difícil culpar o PostgreSQL. Pelos comentários de issues no GitHub, parece que a abordagem mais razoável foi refatorar o ORM para quebrar uma consulta grande em várias menores. Pessoalmente, acho que algo em torno de 3.000~5.000 linhas por consulta é adequado. Alguém sugeriu que uma estratégia com tabela temporária e depois join — especialmente COPY … FROM — dá melhor performance, mas isso exige uma mudança grande no código e, no fim, acabaram desistindo dessa abordagem. No geral, acho que é uma coletânea muito boa de relatos de experiência; serve bem como casos de alerta.

    • Concordo que esse tipo de tentativa já é uma ideia “maldita”. Lendo toda a lista, essa “lista de maldições” parece menos um atalho de armadilha de design e mais um conjunto de lições que o desenvolvedor aprendeu na prática. Claro que a qualidade das informações varia e algumas ainda estão em andamento, mas ela é mais valiosa quando entendida como anotações pessoais de engenharia.

    • Me trouxe a sensação de processar todos os nomes de arquivos de um sistema de arquivos com ferramentas como xargs sem o caractere NUL. Se houver nomes de arquivo estranhos/quebrados ou memória limitada, isso pode dar ruim. O ideal é usar find -print0 junto com parallel -0/xargs -0. E com sed, grep e similares, cuidado para não causar erros de sequência de multibyte ao usar sem LC_ALL=C.

    • Eu mesmo já passei por isso ao fazer upsert em massa com ORM e dar aquele erro de 65 mil bindings. Principalmente quando a tabela tem coluna do tipo array do SQL, cada item inserido precisa ser bindado, então a quantidade de variáveis de bind pode variar. Aí, mesmo que linhas/colunas pareçam iguais em duas execuções, a quantidade de bindings pode mudar.

    • Outra estratégia é passar valores como argumentos de array (text[], int[] etc). O PostgreSQL lida bem com isso. ANY() costuma ser um pouco mais lento que IN(), mas permite armazenar vários IDs em um único parâmetro. Talvez o ORM não tenha suporte para isso.

    • Eu também reparei nisso: bindar tantos parâmetros é claramente uma prática amaldiçoada. Para processamento em massa, em geral deveria-se usar COPY. Para acrescentar mais um caso amaldiçoado do Postgres: nomes de prepared statements são truncados silenciosamente em NAMEDATALEN-1 (onde NAMEDATALEN é 64). Isso acontece desde 2001 e já existia antes também. ORMs precisam levar isso em conta. É raro uma pessoa usar prepared statement name com mais de 60 caracteres, mas ORMs costumam fazer isso.

  • O item de “instalar 50 pacotes adicionais” foi realmente chocante. O autor daquele pacote provavelmente inflou bastante o número de downloads. Se a gente pensar no desperdício de banda e espaço em disco global, é uma pena. Fiquei curioso se isso não foi só para ganhar reputação.

    • O maintainer desse pacote na tal “lista de conhecimento amaldiçoado” é membro do TC39 e já foi figura polêmica em vários projetos conhecidos de JavaScript. Teve alegação de motivação financeira em uma questão específica de polyfill, mas, como o ganho em GitHub Sponsors e Tidelift não é tão grande, achei que talvez ele realmente tenha compatibilidade como um princípio. Em 2025, minha visão sobre isso mudou um pouco. Ele mantém manutenção crítica com consistência e, talvez, o papel de manter opiniões divergentes também seja necessário na comunidade.

    • Pode ser por fama ou personalidade também, mas há uma interpretação extrema de que isso é uma preparação para um ataque de supply chain de larga escala.

    • O autor ali é quase certamente o ljharb.

  • As ADS (Alternate Data Streams) do NTFS do Windows permitem esconder arquivos ilimitados dentro de arquivos existentes.
    O macOS, por padrão, cria uma infinidade de arquivos ocultos e temporários em todos os volumes removíveis — incluindo data fork, xattr e indexação do Spotlight (md). Solução: mdutil -X /Volumes/path/to/vol
    E há telemetria opt-out demais (go, yarn, meilisearch, homebrew, vcpkg, dotnet, Windows, VS Code, Claude Code, macOS, Docker, Splunk, OpenShift, Firefox, Chrome, flutter, e por aí vai).

    • Telemetria opt-out: no caso do go, os dados de telemetria ficam armazenados localmente por padrão. Só ao pedir permissão do usuário é que um subconjunto aprovado é enviado para telemetry.go.dev. O envio pode ser ligado com go telemetry on e desligado completamente com go telemetry off (veja a documentação).

    • Só a telemetria opt-out é que parece realmente útil.

  • Sobre o relato de que “uma requisição HTTP é enviada ao registro do npm toda vez que um script npm é executado”, fiquei em dúvida se isso é verdade. Se for, é um comportamento impensável para um gerenciador de pacotes.

    • Talvez seja parte da verificação de atualização.

    • Provavelmente é isso mesmo por conta de update check. Às vezes aparece aquele banner de atualização.

  • Parece que esqueceu um ponto. O embate sobre tratamento de data/hora em metadados EXIF já é antigo
    Issue de referência 1, issue de referência 2, issue de referência 3

    • Data e hora em si também são fáceis de virar um problema maldito. Mesmo quando funcionam, podem quebrar a qualquer momento em funcionalidades correlatas. Ficam ainda mais suscetíveis se incluírem fuso horário ou horário de verão.
  • Me veio à cabeça o livro “Madness beyond the gates” do Hadoop e Kerberos (link). Esse texto já me salvou várias vezes de chegar perto de surtar. Valeu, Steve, pelo trabalho; dá para imaginar o quanto custou pra extrair esse conhecimento amaldiçoado.

  • O conceito de reunir conhecimento amaldiçoado num único lugar é ótimo. Também faz sentido o relato de tropeços que só aparecem quando você se aprofunda num projeto. Vou fazer ideia de montar uma lista dessas em cada projeto daqui pra frente.

  • Esta entrada não é exatamente “conhecimento amaldiçoado”; é uma questão de segurança e privacidade relacionada a permissões em sistemas móveis.

  • Ótima ideia! Fiquei curioso se outras pessoas também querem compartilhar seus próprios conhecimentos amaldiçoados.
    Na minha experiência, o nome de arquivo no MacOS também é amaldiçoado:

  1. Por padrão, o macOS não diferencia maiúsculas e minúsculas em nomes de arquivo (file.txt e FILE.txt são equivalentes).
  2. Quando o macOS salva nomes de arquivo em NFC, eles podem às vezes ser convertidos para NFD.
  • Em 1995, com o beta do Windows 95, criamos o primeiro CDDB. Distribuímos nomes de faixas de CDs em arquivo .ini, e o projeto foi encerrado por causa do limite de tamanho de 64 KB do arquivo .ini.

  • Correto. Se você cria um volume de sistema ou de dados APFS/HFS+ com case-sensitive, vai dar problema sem dúvida.

  • O item “1” é só configuração padrão. Tanto HFS quanto APFS têm opção case-sensitive. NTFS também funciona de modo parecido. Esses sistemas de arquivos são case-retentive, então dá para fazer algo assim:

 $ echo yup > README.txt
 $ cat ReAdMe.TXT
 yup
 $ ls
 README.txt

O problema real é que o Steam se recusa a instalar em sistemas de arquivos case-sensitive (mesmo havendo versão Linux).