MÓDULO 6.1

🐛 Erros comuns

O bestiário do OpenHuman: CEF lib panic, sidecar legado, OPENHUMAN_CORE_TOKEN ausente, window.__TAURI__ check errado, CORS preflight, deep links macOS e pre-push falhando. Cada sintoma + cada fix.

7
Tópicos
40
Minutos
SOS
Nível
Receita
Tipo
1

💥 CEF lib panic — LibraryLoader::new

Você acabou de clonar o repo, rodou pnpm dev:app e bateu de cara num panic no boot. A culpa quase sempre é o CLI errado.

🚨 Sintoma

thread 'main' panicked at 'CEF library not found':
cef::library_loader::LibraryLoader::new
note: run with `RUST_BACKTRACE=1` for a backtrace

O bundle do app ficou sem o framework Chromium em Contents/Frameworks/.

🔧 Fix

Use o CLI vendored — ele é o único que sabe empacotar CEF no bundle.

cargo install --locked --path app/src-tauri/vendor/tauri-cef/crates/tauri-cli
# ou, mais simples:
pnpm tauri:ensure

O alias tauri:ensure roda o script scripts/ensure-tauri-cli.sh que detecta e reinstala o CLI vendored automaticamente.

✓ Correto

  • pnpm dev:app (chama tauri:ensure antes)
  • CLI no PATH: tauri --version mostra build vendored
  • Reinstalar quando atualizar dependências CEF

✗ Errado

  • npm i -g @tauri-apps/cli (stock, sem CEF)
  • cargo tauri dev usando CLI stock
  • Ignorar tauri:ensure "para ir mais rápido"
Diagnóstico
panic + LibraryLoader
Causa
CLI stock sem CEF
Fix
tauri:ensure
Prevenção
Scripts pnpm sempre
2

🗑️ Sidecar legado — esqueça

Docs antigos, tutoriais de blog, até alguns scripts mencionam o "sidecar binary". Spoiler: ele foi removido em PR #1061.

💡 Macete

Se vir pnpm core:stage em algum doc — é só um echo. O core hoje roda in-process como tokio task dentro do Tauri host. Lifecycle inteiro morre quando você dá Cmd+Q.

📐 Como é hoje

  • core_process::CoreProcessHandle em app/src-tauri/src/core_process.rs spawna o JSON-RPC server
  • Frontend ainda fala HTTP local — http://127.0.0.1:<port>/rpc
  • Auth via bearer hex em OPENHUMAN_CORE_TOKEN (per-launch)
  • Para anexar a um core externo: OPENHUMAN_CORE_REUSE_EXISTING=1
PR
#1061 removeu sidecar
Modelo
in-process tokio task
Lifecycle
morre com Cmd+Q
core:stage
é só echo
3

🔑 OPENHUMAN_CORE_TOKEN ausente

Toda chamada RPC ao core leva um bearer hex no header. Sem ele, 401 em tudo — e o app simplesmente trava no boot, sem mensagem clara.

🔬 Como o token é gerado

  • • Quando o app sobe, o CoreProcessHandle gera um hex aleatório
  • • Esse hex vai pra env OPENHUMAN_CORE_TOKEN do processo
  • • Também é gravado em {workspace}/core.token (default ~/.openhuman/core.token)
  • • Cada launch reseta — não tente persistir entre runs

⚠️ Quando você dá tiro no pé

Rodando o core como standalone para debug e esquecendo o token no header:

# Sobe core standalone
./target/debug/openhuman-core serve

# Em outro shell:
curl http://127.0.0.1:9020/rpc -d '{...}'
# → HTTP/1.1 401 Unauthorized
# → {"error":"missing bearer token"}

✅ Fix

TOKEN=$(cat ~/.openhuman-staging/core.token)
curl -sS http://127.0.0.1:9020/rpc \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"jsonrpc":"2.0","id":1,"method":"core.ping","params":{}}'
Sintoma
401 silencioso
Token
per-launch hex
Arquivo
{workspace}/core.token
Header
Authorization: Bearer
4

🪟 window.__TAURI__ check errado

Tentação natural: "estou no Tauri? if (window.__TAURI__) resolve". Falso. Essa propriedade não existe no module load — está disponível só depois do bridge inicializar.

✗ Errado

// Carrega no boot do bundle JS
if (window.__TAURI__) {
  // ❌ false em 100% dos casos!
  setupTauriHandlers();
}

Setup nunca roda. Silencioso.

✓ Correto

import { isTauri } from
  '@/services/webviewAccountService';

if (isTauri()) {
  // ✅ usa o wrapper canônico
  setupTauriHandlers();
}

Wrapper sabe esperar o bridge.

💡 Alternativa robusta

try {
  await invoke('greet', { name: 'world' });
  // estamos no Tauri
} catch {
  // browser puro ou bridge ainda não pronto
}

Quando o code path realmente precisa chamar IPC, abraçar com try/catch também serve como detecção de ambiente.

API
isTauri()
Origem
webviewAccountService
Banido
window.__TAURI__
Fallback
try/catch invoke
5

🌐 CORS preflight em fetch — não use fetch

Você vê o core escutando em 127.0.0.1:9020 e pensa: "óbvio, fetch('http://127.0.0.1:9020/rpc')". E aí o navegador dispara um OPTIONS preflight que falha por falta de header CORS.

1

Você chama fetch com Content-Type custom

Header application/json + body POST = preflight automático.

2

Navegador manda OPTIONS

Espera Access-Control-Allow-* de volta. Core não emite — request abortada.

3

Use IPC nativo

invoke('core_rpc_relay', ...) trafega pelo bridge Tauri — sem navegador, sem CORS.

📋 Código real

import { invoke } from '@tauri-apps/api/core';

// Use sempre o relay — nunca fetch direto
const response = await invoke('core_rpc_relay', {
  method: 'openhuman.memory_list',
  params: { limit: 50 }
});
Causa
Preflight OPTIONS
Fix
core_rpc_relay
Cliente
coreRpcClient
Nunca
fetch(127.0.0.1)
6

🍎 Deep links macOS — só com .app bundle

Você está debugando OAuth no tauri dev. O navegador abre o callback openhuman://auth?... e... nada acontece. O app continua na tela de welcome. Antes de jurar que é bug, leia abaixo.

⚠️ Limitação real do macOS

O Launch Services do macOS só associa URL schemes a um .app instalado com Info.plist contendo o CFBundleURLTypes. Em tauri dev o binário não tem essa associação formal — então o deep link "morre" no browser.

💡 Receita para testar

pnpm test:e2e:build    # build do bundle .app
open target/release/bundle/macos/OpenHuman.app
# agora o URL scheme está registrado
# tente o OAuth de novo

🔍 Outros pontos do checklist

  • • Só UMA instância do OpenHuman aberta (senão Launch Services manda pra outra)
  • • Se usa core remoto, confirme que recebeu openhuman.auth_store_session
  • • Para core externo, injete o JWT manual com curl para isolar o problema
  • • Não cole JWTs reais em issues públicas — redact tokens
Plataforma
macOS Launch Services
Bloqueio
tauri dev sem associação
Fix
build .app antes
Regra
1 instância só
7

🚧 Pre-push hook falhando — quando --no-verify é OK

Husky roda pnpm rust:check antes de cada push. Às vezes a falha é em código que você nunca tocou — main quebrado, breakage upstream, etc. A regra é clara: diagnose primeiro, escolha consciente depois.

✓ --no-verify é OK quando…

  • Falha em arquivo que você não modificou
  • Você verificou que main também falha
  • Você declara o bypass no PR body
  • CI vai re-rodar e validar mesmo assim

✗ --no-verify NUNCA quando…

  • Falha em código SEU — fix antes
  • Pulando hooks de commit signing
  • Skip pra "ir mais rápido" sem entender
  • Force-push em main sem aprovação

📋 Workflow recomendado

# 1. Rode o check manualmente
pnpm rust:check

# 2. Se falhar, isole — é seu código?
git stash && pnpm rust:check     # main puro ainda falha?

# 3. Se main já está quebrado, --no-verify + nota no PR
git push --no-verify

# Caso contrário: fix, re-stage, re-push
Hook
Husky pre-push
Comando
pnpm rust:check
Escape
--no-verify com nota
Backup
CI valida tudo

🧰 Resumo do Módulo

CEF lib panic — sempre use CLI vendored via pnpm tauri:ensure.
Sidecar morreu — core é in-process desde PR #1061; core:stage é no-op.
Token bearer — per-launch, em {workspace}/core.token.
isTauri() sempre — nunca window.__TAURI__ direto.
RPC via invoke — fetch local dispara CORS preflight.
Deep links macOS — build .app antes de testar OAuth.
Pre-push--no-verify só se a falha não é sua.

Próximo Módulo:

6.2 — 📜 Debug logging: filosofia verbose, prefixos grep-friendly, scripts/debug.