{"record":{"id":"bc0c5ba0f9c79942","repo":"pear-devs/pear-desktop","slug":"bad-httpstatus-response-statustext","errorCode":null,"errorMessage":"bad HTTPStatus(${response.statusText})","messagePattern":"bad HTTPStatus\\((.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/plugins/synced-lyrics/providers/LRCLib.ts","lineNumber":34,"sourceCode":"    album,\n    songDuration,\n    tags,\n  }: SearchSongInfo): Promise<LyricResult | null> {\n    let query = new URLSearchParams({\n      artist_name: artist,\n      track_name: title,\n    });\n\n    query.set('album_name', album!);\n    if (query.get('album_name') === 'undefined') {\n      query.delete('album_name');\n    }\n\n    let url = `${this.baseUrl}/api/search?${query.toString()}`;\n    let response = await fetch(url);\n\n    if (!response.ok) {\n      throw new Error(`bad HTTPStatus(${response.statusText})`);\n    }\n\n    let data = (await response.json()) as LRCLIBSearchResponse;\n    if (!data || !Array.isArray(data)) {\n      throw new Error(`Expected an array, instead got ${typeof data}`);\n    }\n\n    if (data.length === 0) {\n      if (!config()?.showLyricsEvenIfInexact) {\n        return null;\n      }\n\n      // Try to search with the alternative title (original language)\n      const trackName = alternativeTitle || title;\n      query = new URLSearchParams({ q: `${trackName}` });\n      url = `${this.baseUrl}/api/search?${query.toString()}`;\n\n      response = await fetch(url);","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/pear-devs/pear-desktop/blob/1e2aac5706c870c93ed74ba8727ae8390d3b0fa5/src/plugins/synced-lyrics/providers/LRCLib.ts#L16-L52","documentation":"The LRCLib lyrics provider searches lrclib.net; if the first HTTP response (artist/track/album query) returns a non-OK status, it throws an error embedding response.statusText. This is a plain network/HTTP failure against the LRCLib API.","triggerScenarios":"lrclib.net being down or returning 5xx; 429 rate limiting from too many lyric lookups; 4xx from bad query params; DNS/TLS failures surface as fetch rejects (different error), but any non-2xx status triggers this; proxy or firewall rewriting responses.","commonSituations":"Rapid song switching triggering rate limits; LRCLib outages; corporate networks blocking the API; offline usage.","solutions":["Retry with backoff — LRCLib rate limits are often transient","Wrap the provider call and fall back to another provider (Megalobiz, Genius) or show no lyrics","Cache successful lyric lookups to reduce request volume","Check https://lrclib.net directly to distinguish outage from local network issues"],"exampleFix":"// before\nconst result = await lrclib.search(info);\n\n// after\nlet result: LyricResult | null = null;\ntry { result = await lrclib.search(info); }\ncatch (e) { if (!/bad HTTPStatus/.test(e.message)) throw e; result = await megalobiz.search(info); }","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"const withRetry = async <T>(fn: () => Promise<T>, n = 3) => {\n  for (let i = 0; ; i++) {\n    try { return await fn(); }\n    catch (e) {\n      if (i >= n - 1 || !/bad HTTPStatus/.test(e.message)) throw e;\n      await new Promise(r => setTimeout(r, 1000 * 2 ** i));\n    }\n  }\n};\nconst r = await withRetry(() => lrclib.search(info));","preventionTips":["Cache lyric results to cut request volume","Fall back to another provider after retries","Space out searches during rapid track changes to dodge rate limits"],"tags":["lyrics","lrclib","http","network","rate-limit"],"backgroundTag":"http-error-response","analyzedSha":"1e2aac5706c870c93ed74ba8727ae8390d3b0fa5","analyzedAt":"2026-08-27T20:01:08.614Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}