tonhowtf/omniget · error

Token sem value

Error message

Token sem value

What it means

Thrown in fetch_access_token when the Twitch playback access token JSON has a signature but no string "value" field. Both signature and value are required to build the authenticated playback URL (AccessToken struct), so the library fails fast with this Portuguese message ("Token without value").

Solutions

  1. Log the raw token_obj JSON to see actual keys
  2. Validate the clip exists and is not restricted before requesting a token
  3. Update parsing to match the current Twitch GQL schema
  4. Retry once — intermittent Twitch responses can omit fields

Example fix

// before
let value = token_obj.get("value").and_then(|v| v.as_str()).ok_or_else(|| anyhow!("Token sem value"))?.to_string();
// after
let value = token_obj.get("value")
    .and_then(|v| v.as_str())
    .ok_or_else(|| anyhow!("Token sem value; response keys: {:?}", token_obj.as_object().map(|o| o.keys().collect::<Vec<_>>())))?;
.to_string();
Defensive patterns

Strategy: validation

Validate before calling

fn has_valid_token(obj: &serde_json::Value) -> bool {
    obj.get("signature").and_then(|v| v.as_str()).is_some()
        && obj.get("value").and_then(|v| v.as_str()).is_some()
}

Type guard

fn is_string_field(v: &serde_json::Value, key: &str) -> Option<&str> {
    v.get(key).and_then(|x| x.as_str())
}

Prevention

When it happens

Trigger: Twitch's GQL PlaybackAccessToken response object contains signature but the "value" key is missing, null, or not a string.

Common situations: Twitch schema changes; partial/degraded API responses; clip restricted so Twitch returns a truncated token object.

Related errors


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

Appendix: source

Thrown at src-tauri/omniget-core/src/platforms/twitch.rs:243

        let json: serde_json::Value = response.json().await?;

        let token_obj = json
            .as_array()
            .and_then(|arr| arr.first())
            .and_then(|r| r.pointer("/data/clip/playbackAccessToken"))
            .ok_or_else(|| anyhow!("Access token not available for clip: {}", slug))?;

        let signature = token_obj
            .get("signature")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow!("Token sem signature"))?
            .to_string();

        let value = token_obj
            .get("value")
            .and_then(|v| v.as_str())
            .ok_or_else(|| anyhow!("Token sem value"))?
            .to_string();

        Ok(AccessToken { signature, value })
    }

    fn build_authenticated_url(source_url: &str, token: &AccessToken) -> String {
        format!(
            "{}?sig={}&token={}",
            source_url,
            urlencoding::encode(&token.signature),
            urlencoding::encode(&token.value),
        )
    }
}

#[async_trait]
impl PlatformDownloader for TwitchClipsDownloader {
    fn name(&self) -> &str {

View on GitHub (pinned to 8600b91f42)