{"record":{"id":"56901dbc0b46f970","repo":"pear-devs/pear-desktop","slug":"token-not-initialized","errorCode":null,"errorMessage":"Token not initialized","messagePattern":"Token not initialized","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/plugins/synced-lyrics/providers/MusixMatch.ts","lineNumber":194,"sourceCode":"      this.cookie = 'x-mxm-user-id=';\n      localStorage.removeItem(this.key);\n      this.initPromise = this.init();\n      await this.initPromise;\n    }\n  }\n\n  // god I love typescript generics, they're so useful\n  public async query<\n    T extends Endpoint,\n    R = {\n      header: { status_code: number };\n      body: T extends keyof typeof ResponseSchema\n        ? z.infer<(typeof ResponseSchema)[T]>\n        : unknown;\n    },\n  >(endpoint: T, params: Params[T]): Promise<R> {\n    await this.initPromise;\n    if (!this.token) throw new Error('Token not initialized');\n\n    const url = `${this.baseUrl}${endpoint}`;\n\n    const clonedParams = new URLSearchParams(\n      Object.assign(\n        {\n          app_id: this.app_id,\n          format: 'json',\n          usertoken: this.token,\n        },\n        <Record<string, string>>params,\n      ),\n    );\n\n    const [, json, headers] = await netFetch(`${url}?${clonedParams}`, {\n      headers: { Cookie: this.cookie },\n    });\n","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/pear-devs/pear-desktop/blob/1e2aac5706c870c93ed74ba8727ae8390d3b0fa5/src/plugins/synced-lyrics/providers/MusixMatch.ts#L176-L212","documentation":"MusixMatch provider throws 'Token not initialized' when query() is invoked before the async token initialization has completed or if initialization failed to set a token. The method awaits this.initPromise and then checks this.token, so any init failure (e.g. 'Failed to get token') surfaces here as this error on subsequent API calls. It indicates the provider was never able to authenticate against the MusixMatch API.","triggerScenarios":"Calling any lyrics lookup (this.data()/query()) before init() finishes, after init() threw 'Failed to get token', or after the cached token was removed from localStorage and reinit failed (network error or changed token endpoint).","commonSituations":"Offline or proxied environment blocking the token fetch, MusixMatch changing their token scraping endpoint/HTML structure, corrupted localStorage entry under this.key, or racing the provider's construction against an immediate query call.","solutions":["Check network access to the MusixMatch token endpoint and retry (call reinit()) once connectivity is restored.","Clear the cached token entry in localStorage (this.key) and call reinit() to force a fresh token fetch.","Inspect getToken()/savedTokenSchema parsing — if MusixMatch changed their page structure, update the token extraction logic.","Ensure you await the provider's initialization (or the first query) before showing results, so init errors surface clearly instead of this secondary error."],"exampleFix":"// before\nconst lyrics = await provider.query('matcher.lyrics.get', { q_track: '...' });\n\n// after\ntry {\n  const lyrics = await provider.query('matcher.lyrics.get', { q_track: '...' });\n} catch (e) {\n  if (e instanceof Error && e.message === 'Token not initialized') {\n    await provider.reinit();\n    // retry once after re-initialization\n  }\n}","handlingStrategy":"retry","validationCode":"// before querying, ensure the provider initialized successfully\nawait provider.initPromise; // rethrows init failure early, or:\nif (!provider.token) {\n  await provider.reinit();\n}","typeGuard":"const isTokenNotInitialized = (e: unknown): boolean =>\n  e instanceof Error && e.message === 'Token not initialized';","tryCatchPattern":"try {\n  const res = await provider.query('matcher.subtitle.get', params);\n} catch (e) {\n  if (isTokenNotInitialized(e)) {\n    await provider.reinit();\n    return provider.query('matcher.subtitle.get', params); // one retry\n  }\n  throw e;\n}","preventionTips":["Always await the provider's init (or initPromise) before the first query.","Treat consecutive failures as a signal to disable the MusixMatch provider and fall back to other providers.","Clear the cached localStorage token when debugging init issues."],"tags":["musixmatch","token","initialization","synced-lyrics","auth"],"backgroundTag":"auth-token-not-initialized","analyzedSha":"1e2aac5706c870c93ed74ba8727ae8390d3b0fa5","analyzedAt":"2026-08-27T20:01:08.614Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}