tonhowtf/omniget · error · anyhow

o device flow precisa do client_secret da sua app do Trakt

Error message

o device flow precisa do client_secret da sua app do Trakt

What it means

Thrown by wait_for_token when the stored config has no client_secret. Trakt's device-flow token exchange (/oauth/device/token) requires client_secret alongside device_code, so polling cannot proceed without it.

Solutions

  1. Copy the client_secret from the app page at https://trakt.tv/oauth/applications
  2. Save it into the Trakt config store before calling wait_for_token()
  3. Re-run the device flow (device_code + wait_for_token) once both credentials are stored
Defensive patterns

Strategy: validation

Validate before calling

if config.client_secret.trim().is_empty() {
    return Err("configure o client_secret do Trakt antes de conectar".into());
}

Type guard

fn has_client_secret(c: &TraktConfig) -> bool { !c.client_secret.trim().is_empty() }

Prevention

When it happens

Trigger: Calling wait_for_token() with a config whose client_secret field is empty — the app only registered client_id, or the secret was cleared by a config reset.

Common situations: User pasted only the client_id during setup; secret field lost after editing/migrating the config; app was recreated on Trakt and the old secret no longer exists.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/fc3806639dedb9ae. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/lists/trakt.rs:297

    })
}

#[derive(Debug, Clone, Serialize)]
pub struct ConnectResult {
    pub connected: bool,
    pub username: String,
    pub message: String,
}

/// Passo 2: consulta até o usuário liberar (ou o código morrer). Respeita o
/// intervalo pedido e recua quando leva 429.
pub async fn wait_for_token(dc: &DeviceCode, p: ProgressFn) -> Result<ConnectResult> {
    let c = {
        let _g = LOCK.lock().unwrap_or_else(|e| e.into_inner());
        load()
    };
    if c.client_secret.is_empty() {
        return Err(anyhow!(
            "o device flow precisa do client_secret da sua app do Trakt"
        ));
    }
    let http = client()?;
    let started = Instant::now();
    let deadline = Duration::from_secs(dc.expires_in.clamp(60, 1800));
    let mut interval = Duration::from_secs(dc.interval);
    loop {
        if started.elapsed() >= deadline {
            return Err(anyhow!("{}", Poll::Expired.message()));
        }
        tokio::time::sleep(interval).await;
        let left = deadline.saturating_sub(started.elapsed()).as_secs();
        report(
            &p,
            TOOL_ID,
            "progress",
            started.elapsed().as_secs(),

View on GitHub (pinned to 8600b91f42)