Ruby 4.0 removeu gems dos defaults e quebrou dependência transitiva
TLDR:
u-case→kindfazrequire "ostruct"sem declarar a dependência; no Ruby 4.0ostructdeixou de ser default gem e a suíte parou de bootar. Correção: declararostructno Gemfile do app.
O que aconteceu
A suíte do modules/backend deixou de bootar com cannot load such file. O erro não vinha de código
nosso nem de uma gem que declaramos — vinha de uma dependência transitiva.
Causa raiz
No Ruby 4.0, várias gems de stdlib deixaram de ser default gems (ostruct, entre outras). Gems que
fazem require delas sem declará-las no gemspec quebram no boot.
O caso concreto: u-case depende de kind, e kind 6.0.1 faz require "ostruct" sem declarar a
dependência — o gemspec dela não tem nenhuma dependência de runtime. Até o Ruby 3.4 isso funcionava
por acidente, porque ostruct estava sempre disponível como default gem.
mermaid
graph LR
A["app (Gemfile)"] --> B["u-case"]
B --> C["kind 6.0.1"]
C -.->|"require 'ostruct'<br/>não declarado"| D["ostruct"]
D -->|"Ruby ≤ 3.4"| E["default gem ✓"]
D -->|"Ruby 4.0"| F["ausente ✗"]
style F fill:#7f1d1d,color:#fff
Correção
Declarar a gem no Gemfile do app até a dependência corrigir o próprio gemspec:
ruby
# stdlib gem removed from Ruby 4.0 defaults, still required by u-case's kind dependency
gem "ostruct"
Como evitar
- O próprio Ruby avisa antes de quebrar:
X used to be loaded from the standard library, but is not part of the default gems since Ruby 4.0.0. Tratar esse warning como erro em CI antecipa o problema para antes do upgrade. - Ao subir a versão do Ruby, o erro de boot indica qual gem tentou o
require— a correção é sempre no Gemfile do app, com comentário explicando por que a gem está lá (senão ela parece órfã e alguém a remove). - O mesmo padrão vale para as outras gems que saíram dos defaults, não só
ostruct.