pear-devs/pear-desktop · error · Error
bad HTTPStatus(${response.statusText})
Error message
bad HTTPStatus(${response.statusText}) What it means
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.
Source
Thrown at src/plugins/synced-lyrics/providers/LRCLib.ts:34
album,
songDuration,
tags,
}: SearchSongInfo): Promise<LyricResult | null> {
let query = new URLSearchParams({
artist_name: artist,
track_name: title,
});
query.set('album_name', album!);
if (query.get('album_name') === 'undefined') {
query.delete('album_name');
}
let url = `${this.baseUrl}/api/search?${query.toString()}`;
let response = await fetch(url);
if (!response.ok) {
throw new Error(`bad HTTPStatus(${response.statusText})`);
}
let data = (await response.json()) as LRCLIBSearchResponse;
if (!data || !Array.isArray(data)) {
throw new Error(`Expected an array, instead got ${typeof data}`);
}
if (data.length === 0) {
if (!config()?.showLyricsEvenIfInexact) {
return null;
}
// Try to search with the alternative title (original language)
const trackName = alternativeTitle || title;
query = new URLSearchParams({ q: `${trackName}` });
url = `${this.baseUrl}/api/search?${query.toString()}`;
response = await fetch(url);View on GitHub (pinned to 1e2aac5706)
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
Example fix
// before
const result = await lrclib.search(info);
// after
let result: LyricResult | null = null;
try { result = await lrclib.search(info); }
catch (e) { if (!/bad HTTPStatus/.test(e.message)) throw e; result = await megalobiz.search(info); } Defensive patterns
Strategy: retry
Try / catch
const withRetry = async <T>(fn: () => Promise<T>, n = 3) => {
for (let i = 0; ; i++) {
try { return await fn(); }
catch (e) {
if (i >= n - 1 || !/bad HTTPStatus/.test(e.message)) throw e;
await new Promise(r => setTimeout(r, 1000 * 2 ** i));
}
}
};
const r = await withRetry(() => lrclib.search(info)); Prevention
- 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
When it happens
Trigger: 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.
Common situations: Rapid song switching triggering rate limits; LRCLib outages; corporate networks blocking the API; offline usage.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- bad HTTPStatus(${response.statusText})
- Expected an array, instead got ${typeof data}
- Failed to extract lyrics from preloaded state.
- Failed to extract lyrics from page.
- Failed to get token
AI-assisted analysis of pear-devs/pear-desktop@1e2aac5706 (2026-08-27).
Data as JSON: /api/errors/bc0c5ba0f9c79942.
Report an issue: GitHub.