Recentemente, passei muito mais tempo do que gostaria perseguindo um crash duro após atualizar um projeto do Expo SDK 54 para o 55.
O aplicativo iniciou bem. A navegação funcionava. Tudo parecia normal.
No momento em que uma animação Reanimated foi acionada, o aplicativo explodiu com uma tela vermelha:
Erro ao renderizar
global._getAnimationTimestamp não é uma função (está indefinida)
No meu caso, o crash aconteceu dentro de um useEffect que chamava withTiming() em um valor compartilhado quando uma aba ganhou foco.
A minha primeira suposição foi um problema de dependência entre react-native-reanimated e react-native-worklets. Verifiquei as versões, verifiquei a árvore de dependências e até comecei a procurar por problemas de configuração do Babel.
Tudo parecia correto.
No final das contas, o problema não estava no código JavaScript em absoluto.
O que está realmente acontecendo?
A primeira impressão é de que este erro parece ser uma mudança quebra tudo dentro do Reanimated ou uma má configuração do projeto.
No entanto, na realidade, geralmente é um problema de sincronização entre o seu bundle JavaScript e o binário nativo do aplicativo.
A pista importante é o nome da função em si:
_getAnimationTimestamp
Esta não é uma função que seu aplicativo chama diretamente. É uma das funções internas que o Reanimated espera encontrar no runtime nativo.
O Reanimated depende fortemente de JSI (JavaScript Interface) para criar um bridge direto entre JavaScript e código C++ nativo para trabalho de animação crítico ao desempenho.
Quando você atualiza para o Expo SDK 55, o Reanimated também é atualizado (geralmente de 4.1.x para 4.2.x, dependendo do seu projeto).
O servidor Metro começa imediatamente a servir o bundle JavaScript atualizado.
A questão é que seu cliente de desenvolvimento personalizado ainda está executando o código nativo compilado antes da atualização.
Atualmente, você tem duas versões diferentes se comunicando:
- O lado JavaScript espera a implementação mais recente do runtime Reanimated.
- O lado nativo ainda expõe a implementação anterior.
O bundle JavaScript atualizado espera que _getAnimationTimestamp exista.
O seu cliente nativo mais antigo ainda não fornece essa função.
No momento em que o Reanimated tenta usá-la, o aplicativo cai.
Por que reinstalar dependências não ajuda
Passei pela lista de verificação habitual primeiro:
- Reinstalar dependências
- Verificar versões de pacotes
- Checar configuração do Babel
- Limpar
node_modules - Rode novamente o comando
npm install
Nenhuma dessas ações resolveu o problema.
Isto é porque o problema não está nas suas dependências JavaScript.
Sua aplicação pode estar perfeitamente correta enquanto seu dispositivo ou simulador ainda estiver rodando um binário nativo desatualizado.
Enquanto o cliente nativo não foi reconstruído após a atualização, o crash continuará acontecendo.
Quando você verá este erro
Um ponto importante é que isso geralmente aparece quando você está usando um cliente de desenvolvimento personalizado.
Caso esteja utilizando o Expo Go, o Expo gerencia a execução nativa para você, então JavaScript e código nativo geralmente permanecem em sincronia.
Este problema é muito mais comum quando:
- Você está trabalhando com clientes de desenvolvimento personalizados
expo run:androidexpo run:ios- Cria builds de desenvolvimento através do EAS
Nesses ambientes, é possível que o Metro esteja servindo novos arquivos JavaScript enquanto seu dispositivo ainda está rodando uma versão nativa mais antiga.
A Solução
Um recarregamento normal de JavaScript não resolverá isso.
Clicar em r no terminal do Metro apenas atualiza o bundle JavaScript. Não reconstrói a aplicação nativa.
Para corrigir o problema, você precisa que ambas as partes da aplicação estejam rodando a mesma versão.
Passo 1: Limpar cache do Metro
Pare completamente o Metro e reinicie-o com um cache limpo:
npx expo start -c
Isto remove a possibilidade do Metro servir arquivos transformados desatualizados.
Passo 2: Reconstruir o Cliente Nativo
Caso esteja construindo localmente, gere uma nova aplicação nativa:
npx expo run:ios
# ou
npx expo run:android
Isto recompila o código nativo usando as versões instaladas atualmente em seu projeto.
Passo 3: Reconstruir o Build de Desenvolvimento (EAS)
Caso esteja usando builds de desenvolvimento do EAS, você precisará gerar um novo build completo e instalá-lo em seu dispositivo.
Depois que a build terminar, instale o novo IPA ou APK e inicie o cliente atualizado.
Por Que Esta Solução Funciona
Após a recompilação, ambos os lados do aplicativo finalmente estão usando a mesma versão de Reanimated:
- O Metro serve o bundle JavaScript atualizado.
- A binária nativa contém as associações JSI correspondentes.
Quando essas versões se alinham novamente, o Reanimated consegue encontrar as funções que espera e a falha desaparece.
Uma Nota Rápida sobre Depuração
Este foi um dos erros que inicialmente parecia ser uma questão de dependência, depois um problema do Babel e então um problema do Reanimated.
No entanto, na realidade era apenas uma build nativa desatualizada.
Problemas como esse são uma das partes mais frustrantes do React Native porque a mensagem de erro raramente aponta para a causa real. É fácil passar horas verificando versões de pacotes quando o verdadeiro reparo é simplesmente recompilar o cliente nativo.
Depois de passar muitas noites vasculhando traços de pilha, problemas do GitHub e fóruns antigos, acabei criando uma pequena ferramenta chamada Fix My Error.
Você cola a saída de erro, e ela ajuda a identificar causas prováveis e soluções sem ter que navegar entre dez abas diferentes procurando alguém que tenha enfrentado o mesmo problema há três anos.
Para este erro em particular, no entanto, a solução acabou sendo muito mais simples do que eu esperava: limpe o Metro, recompile o cliente nativo e garanta que seu bundle JavaScript e runtime nativo realmente estão executando a mesma versão.

