tonhowtf/omniget · error · Error
Track sem soundcloud_id
Error message
Track sem soundcloud_id
What it means
Raised by fetch_access_token when the token GQL response is valid JSON but does not contain /data/clip/playbackAccessToken on the first array element. The response is expected to be an array of query results; without the playbackAccessToken object no download URLs can be signed.
Solutions
- Log the full token response JSON and compare against the expected {data:{clip:{playbackAccessToken:{signature,value}}}} shape; update pointers if it changed.
- Check whether the clip requires authentication (sub-only/age-gated) and add OAuth if so.
- Handle the empty-array case explicitly to distinguish 'no response' from 'wrong shape'.
- Test the same GQL query manually (curl with client-id) to confirm it still works.
Example fix
// before
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))?;
// after
let token_obj = json.as_array()
.and_then(|arr| arr.first())
.and_then(|r| r.pointer("/data/clip/playbackAccessToken"));
let token_obj = match token_obj {
Some(t) if !t.is_null() => t,
_ => anyhow::bail!("No playbackAccessToken for {} — response: {}", slug, json),
}; Defensive patterns
Strategy: type-guard
Type guard
fn extract_token(json: &serde_json::Value) -> Option<&serde_json::Value> {
json.as_array()?
.first()?
.pointer("/data/clip/playbackAccessToken")
.filter(|t| t.get("signature").is_some() && t.get("value").is_some())
} Try / catch
// Narrow the response before using it
match extract_token(&json) {
Some(token) => build_url(token),
None => bail!("unexpected token response: {}", json),
} Prevention
- Log the full token response whenever shape assumptions break
- Add a contract test on the GQL token query shape
- Handle the empty-array response case explicitly
- Check clip auth requirements (sub-only/age-gated clips may omit tokens)
When it happens
Trigger: json.as_array() is not an array, first() is missing (empty array), or the first element lacks data.clip.playbackAccessToken — combined via the and_then chain into ok_or_else.
Common situations: Twitch changing the GQL response envelope (no longer an array); token request rejected silently for restricted/geo-blocked clips; schema change renaming playbackAccessToken; anonymous token requests denied for some clips.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- SoundCloud nao retornou URL
- Spotify SDK device not ready
- Access token not available for clip
- Token sem signature
- Token sem value
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/1d0bb70244a79cfe.
Report an issue: GitHub.
Appendix: source
Thrown at src/lib/study-music/soundcloud-store.svelte.ts:442
}
await pluginInvoke("study", "study:soundcloud:like:add", { trackId });
return true;
}
async playTrack(track: ScTrack, queue?: ScTrack[]): Promise<void> {
const local = scTrackToMusicTrack(track);
const localQueue = (queue && queue.length > 0 ? queue : [track]).map(scTrackToMusicTrack);
await musicPlayer.play(local, localQueue);
}
}
export const soundcloudStore = new SoundCloudStore();
async function resolveSoundcloudStream(
track: MusicTrack,
): Promise<{ url: string; is_hls: boolean }> {
const scId = (track as any).soundcloud_id as number | undefined;
if (!scId) throw new Error("Track sem soundcloud_id");
const res = await pluginInvoke<{ url: string; is_hls: boolean }>(
"study",
"study:soundcloud:stream:resolve",
{ trackId: scId, quality: "progressive" },
);
if (!res.url) throw new Error("SoundCloud nao retornou URL");
return res;
}
if (typeof window !== "undefined") {
(musicPlayer as any).soundcloudResolver = resolveSoundcloudStream;
}
View on GitHub (pinned to 8600b91f42)