{"record":{"id":"933fe4b5dc1c2ba6","repo":"pear-devs/pear-desktop","slug":"failed-to-extract-lyrics-from-preloaded-state","errorCode":null,"errorMessage":"Failed to extract lyrics from preloaded state.","messagePattern":"Failed to extract lyrics from preloaded state\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/plugins/synced-lyrics/providers/LyricsGenius.ts","lineNumber":82,"sourceCode":"      },\n    ) as HTMLScriptElement;\n\n    const preloadedState = preloadedStateScript.textContent?.match(\n      preloadedStateRegex,\n    )?.[1]?.replace(/\\\\\"/g, '\"');\n\n    const lyricsHtml = preloadedState?.match(preloadHtmlRegex)?.[1]\n      ?.replace(/\\\\\\//g, '/')\n      ?.replace(/\\\\\\\\/g, '\\\\')\n      ?.replace(/\\\\n/g, '\\n')\n      ?.replace(/\\\\'/g, \"'\")\n      ?.replace(/\\\\\"/g, '\"');\n\n    const hasUnreleasedPlaceholder = preloadedState &&\n      /lyricsPlaceholderReason.{1,5}unreleased/.test(preloadedState);\n    if (!lyricsHtml) {\n      if (hasUnreleasedPlaceholder) return null;\n      throw new Error('Failed to extract lyrics from preloaded state.');\n    }\n\n    const lyricsDoc = this.domParser.parseFromString(lyricsHtml, 'text/html');\n    const lyrics = lyricsDoc.body.innerText;\n\n    if (lyrics.trim().toLowerCase().replace(/[[\\]]/g, '') === 'instrumental') {\n      return null;\n    }\n\n    return {\n      title: closestHit.result.title,\n      artists: closestHit.result.primary_artists.map(({ name }) => name),\n      lyrics,\n    };\n  }\n}\n\ninterface LyricsGeniusSearch {","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/pear-devs/pear-desktop/blob/1e2aac5706c870c93ed74ba8727ae8390d3b0fa5/src/plugins/synced-lyrics/providers/LyricsGenius.ts#L64-L100","documentation":"The Genius lyrics provider fetches the song page and extracts lyrics from its __PRELOADED_STATE__ JSON embedded in the page. If the expected lyrics HTML fragment cannot be found in that state, it throws 'Failed to extract lyrics from preloaded state.' — unless the page indicates the song is unreleased, in which case it returns null.","triggerScenarios":"Genius changing their page structure (renaming the preloaded-state key or lyrics field); instrumented/lyrics-less pages (e.g. album or artist pages matched by mistake); pages where lyrics live behind interstitials; non-song results for the search query.","commonSituations":"Site redesigns by Genius breaking scrapers (recurring); region or bot checks serving a challenge page instead of the song page; tracks whose Genius page has no lyrics (instrumental entries without the placeholder marker).","solutions":["Update the synced-lyrics plugin — Genius scraping breaks periodically and gets patched","Fall back to LRCLib/Megalobiz when this error occurs","Return null (no lyrics) in the UI rather than crashing the lyrics panel","If it reproduces for all tracks, suspect bot-blocking and verify genius.com loads normally in a browser"],"exampleFix":"// before\nconst r = await genius.search(info);\n\n// after\ntry { return await genius.search(info); }\ncatch (e) {\n  if (!/preloaded state/.test(e.message)) throw e;\n  return await lrclib.search(info);\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { return await genius.search(info); } catch (e) { if (!/preloaded state/.test(e.message)) throw e; return await lrclib.search(info); }","preventionTips":["Expect Genius scraping to break periodically — update the plugin when it does","Verify genius.com loads normally in a browser to rule out bot-blocking","Order providers so scraping-based ones (Genius, Megalobiz) are tried after the stable API (LRCLib)"],"tags":["lyrics","genius","scraping","selector-breakage","api-contract"],"backgroundTag":"web-scraping-selector-broken","analyzedSha":"1e2aac5706c870c93ed74ba8727ae8390d3b0fa5","analyzedAt":"2026-08-27T20:01:08.614Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}