pear-devs/pear-desktop · error · Error
Failed to get token
Error message
Failed to get token
What it means
'Failed to get token' is thrown by MusixMatch's init() when getToken() returns a falsy value — i.e. the provider could not extract a valid token from MusixMatch's token endpoint. init() first checks a localStorage-cached token (valid for 60 seconds), removes it if expired, then fetches a fresh one. Because the constructor kicks off init, this error typically surfaces on the first query() call via 'Token not initialized' or as an unhandled rejection.
Source
Thrown at src/plugins/synced-lyrics/providers/MusixMatch.ts:271
token: z.string(),
expires: z.number(),
}),
]);
private key = 'ytm:synced-lyrics:mxm:token';
private async init() {
const { token, expires } = this.savedTokenSchema.parse(
JSON.parse(localStorage.getItem(this.key) ?? '{ "token": null }'),
);
if (token && expires > Date.now()) {
this.token = token;
return;
}
localStorage.removeItem(this.key);
this.token = await this.getToken();
if (!this.token) throw new Error('Failed to get token');
localStorage.setItem(
this.key,
JSON.stringify({ token: this.token, expires: Date.now() + (60 * 1000) }),
);
}
private tokenSchema = z.object({
message: z.object({
body: z
.object({
user_token: z.string(),
})
.optional(),
}),
});
private async getToken() {
const endpoint = 'token.get';View on GitHub (pinned to 1e2aac5706)
Solutions
- Verify network connectivity and that the MusixMatch token URL used in getToken() is still reachable.
- Log the raw token response in getToken() and compare it against savedTokenSchema; update the parsing if MusixMatch changed the format.
- If token fetch is inherently unreliable in your environment, disable the MusixMatch provider and fall back to other lyrics providers.
- Catch the init failure and schedule reinit() with backoff instead of letting the rejection propagate.
Example fix
// before
this.token = await this.getToken();
if (!this.token) throw new Error('Failed to get token');
// after
this.token = await this.getToken();
if (!this.token) {
console.warn('MusixMatch token fetch failed; provider disabled until reinit');
throw new Error('Failed to get token');
} Defensive patterns
Strategy: try-catch
Validate before calling
// preflight reachability before relying on the provider
async function canReachMusixMatch(): Promise<boolean> {
try {
await fetch(MUSIXMATCH_TOKEN_URL, { method: 'HEAD' });
return true;
} catch {
return false;
}
} Type guard
const isTokenFetchFailure = (e: unknown): boolean => e instanceof Error && e.message === 'Failed to get token';
Try / catch
try {
await provider.reinit();
} catch (e) {
if (isTokenFetchFailure(e)) {
provider.enabled = false; // or skip provider for this session
return fallbackProvider;
}
throw e;
} Prevention
- Catch initPromise at construction time so the rejection never becomes unhandled.
- Retry reinit() with backoff on transient network failures.
- Disable the MusixMatch provider via config when running in restricted networks.
When it happens
Trigger: First use of the MusixMatch provider, or 60s after the last token was cached, when the network request for the token fails or the returned content doesn't match savedTokenSchema (z.union).
Common situations: No internet/DNS failure, MusixMatch changing the token endpoint or the token page's markup, corporate proxy blocking the domain, or the extracted token value being empty. Also fires whenever reinit() is called after the cached entry was removed.
Related errors
- Token not initialized
- Failed to parse response from MusixMatch API
- bad HTTPStatus(${response.statusText})
- bad HTTPStatus(${response.statusText})
AI-assisted analysis of pear-devs/pear-desktop@1e2aac5706 (2026-08-27).
Data as JSON: /api/errors/044cc8297f344f4b.
Report an issue: GitHub.