tonhowtf/omniget · error · anyhow
a autorização do Trakt expirou de vez. Conecte a conta de…
Error message
a autorização do Trakt expirou de vez. Conecte a conta de novo (o código aparece aqui e você libera em trakt.tv/activate)
What it means
Thrown by refresh_if_needed when Trakt responds HTTP 400 with 'invalid_grant' to the refresh-token request, meaning the refresh token has been invalidated permanently. The code calls disconnect() to clear the stored session and instructs the user to reconnect via the device flow again.
Solutions
- Reconnect the account: run device_code() and wait_for_token() to get a brand-new session (as the message says, code appears in-app and is activated at trakt.tv/activate)
- Avoid running multiple instances that refresh the same token concurrently
- Persist the refreshed tokens immediately after each successful refresh
- If it keeps happening, check whether Trakt rotated policy on refresh-token reuse
Defensive patterns
Strategy: retry
Validate before calling
// check token age / last refresh time before issuing requests
if last_refresh.elapsed() > MAX_SESSION_AGE {
proactively_reconnect().await?;
} Try / catch
match run().await {
Err(e) if e.to_string().contains("expirou de vez") => {
// launch the device-flow reconnect UX (device_code + wait_for_token)
}
other => other?,
} Prevention
- Persist refreshed tokens immediately after every successful refresh
- Never run multiple instances sharing the same Trakt token store
- Treat any invalid_grant as terminal and re-run the device flow promptly
When it happens
Trigger: POSTing the refresh token to Trakt's token endpoint yields 400 invalid_grant — the refresh token was revoked/expired/already used (the source comment notes Trakt now invalidates refresh tokens on each use and old sessions die).
Common situations: Long-lived sessions where the refresh token was rotated or invalidated server-side; running two instances sharing one Trakt account so a refresh consumes the token; token store out of sync after manual config edits.
Related errors
- conecte a conta do Trakt primeiro (o código aparece aqui e…
- informe o client_id da sua app do Trakt
- informe primeiro o client_id da sua app do Trakt
- o device flow precisa do client_secret da sua app do Trakt
- o Trakt não devolveu o código do dispositivo
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/10bb477dc05780eb.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/tools/lists/trakt.rs:406
let r = client()?
.post(format!("{}/oauth/token", AUTH))
.json(&serde_json::json!({
"refresh_token": c.refresh_token,
"client_id": c.client_id,
"client_secret": c.client_secret,
"redirect_uri": "urn:ietf:wg:oauth:2.0:oob",
"grant_type": "refresh_token",
}))
.send()
.await?;
if !r.status().is_success() {
let status = r.status().as_u16();
let body = r.text().await.unwrap_or_default();
// O Trakt passou a invalidar o refresh token a cada uso, e a sessão
// antiga morre de vez: quando ele diz isso, não adianta insistir.
if status == 400 && body.contains("invalid_grant") {
let _ = disconnect();
return Err(anyhow!(
"a autorização do Trakt expirou de vez. Conecte a conta de novo (o código aparece aqui e você libera em trakt.tv/activate)"
));
}
// Fora isso não é fatal: o token atual ainda pode valer.
tracing::debug!("trakt: refresh recusado (HTTP {})", status);
return Ok(());
}
let v: Value = r.json().await?;
save_token(&v)?;
let _g = LOCK.lock().unwrap_or_else(|e| e.into_inner());
*c = load();
Ok(())
}
// ── Leitura da API ──────────────────────────────────────────────────────
/// Cliente autenticado com freio, no mesmo desenho do Reddit.
struct Api {View on GitHub (pinned to 8600b91f42)